<commit_before>/******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2018 <NAME>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 ******************************************************************************/

#include "jdwp.h"

namespace JDWP
{
// short helper functions to read/write vectors - always preceeded by an int length
template <typename inner>
void ReadVector(CommandData &data, std::vector<inner> &vec,
                std::function<void(CommandData &data, inner &i)> process)
{
  int32_t count = 0;
  data.Read(count);

  vec.resize((size_t)count);
  for(int32_t i = 0; i < count; i++)
    process(data, vec[i]);
}

template <typename inner>
void WriteVector(CommandData &data, const std::vector<inner> &vec,
                 std::function<void(CommandData &data, const inner &i)> process)
{
  int32_t count = (int32_t)vec.size();
  data.Write(count);

  for(int32_t i = 0; i < count; i++)
    process(data, vec[i]);
}

Connection::Connection(Network::Socket *sock)
    : writer(sock, Ownership::Nothing), reader(sock, Ownership::Nothing)
{
  // the first thing we do is write the handshake bytes and expect them immediately echo'd back.
  const int handshakeLength = 14;
  const char handshake[handshakeLength + 1] = "JDWP-Handshake";

  writer.Write(handshake, handshakeLength);
  writer.Flush();

  char response[15] = {};
  reader.Read(response, handshakeLength);

  if(memcmp(handshake, response, 14))
  {
    RDCERR("handshake failed - received >%s< - expected >%s<", response, handshake);
    error = true;
  }
}

Connection::~Connection()
{
  // bail immediately if we're in error state
  if(IsErrored())
    return;

  // otherwise, undo any suspends we might have done that are still outstanding, in case a logic
  // error made us bail while we had the VM suspended. We copy the refcount since Resume()
  // decrements it.
  int ref = suspendRefCount;
  for(int i = 0; i < ref; i++)
    Resume();
}

bool Connection::SendReceive(Command &cmd)
{
  // send the command, and recieve the reply back into the same object.
  // save the auto-generated ID for this command so we can compare it to the reply - we expect a
  // synchronous reply, no other commands in the way.
  uint32_t id = cmd.Send(writer);
  cmd.Recv(reader);

  if(id != cmd.GetID())
  {
    RDCERR("Didn't get matching reply packet for %d/%d", cmd.commandset, cmd.command);
    error = true;
    return false;
  }

  return true;
}

void Connection::SetupIDSizes()
{
  Command cmd(CommandSet::VirtualMachine, 7);
  if(!SendReceive(cmd))
    return;<commit_msg>Add a small sleep into JDWP connection code to workaround JVM bugs<commit_after>/******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2018 <NAME>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 ******************************************************************************/

#include "jdwp.h"

namespace JDWP
{
// short helper functions to read/write vectors - always preceeded by an int length
template <typename inner>
void ReadVector(CommandData &data, std::vector<inner> &vec,
                std::function<void(CommandData &data, inner &i)> process)
{
  int32_t count = 0;
  data.Read(count);

  vec.resize((size_t)count);
  for(int32_t i = 0; i < count; i++)
    process(data, vec[i]);
}

template <typename inner>
void WriteVector(CommandData &data, const std::vector<inner> &vec,
                 std::function<void(CommandData &data, const inner &i)> process)
{
  int32_t count = (int32_t)vec.size();
  data.Write(count);

  for(int32_t i = 0; i < count; i++)
    process(data, vec[i]);
}

Connection::Connection(Network::Socket *sock)
    : writer(sock, Ownership::Nothing), reader(sock, Ownership::Nothing)
{
  // the first thing we do is write the handshake bytes and expect them immediately echo'd back.
  const int handshakeLength = 14;
  const char handshake[handshakeLength + 1] = "JDWP-Handshake";

  writer.Write(handshake, handshakeLength);
  writer.Flush();

  char response[15] = {};
  reader.Read(response, handshakeLength);

  if(memcmp(handshake, response, 14))
  {
    RDCERR("handshake failed - received >%s< - expected >%s<", response, handshake);
    error = true;
  }
}

Connection::~Connection()
{
  // bail immediately if we're in error state
  if(IsErrored())
    return;

  // otherwise, undo any suspends we might have done that are still outstanding, in case a logic
  // error made us bail while we had the VM suspended. We copy the refcount since Resume()
  // decrements it.
  int ref = suspendRefCount;
  for(int i = 0; i < ref; i++)
    Resume();
}

bool Connection::SendReceive(Command &cmd)
{
  // send the command, and recieve the reply back into the same object.
  // save the auto-generated ID for this command so we can compare it to the reply - we expect a
  // synchronous reply, no other commands in the way.
  uint32_t id = cmd.Send(writer);
  cmd.Recv(reader);
  Threading::Sleep(10);

  if(id != cmd.GetID())
  {
    RDCERR("Didn't get matching reply packet for %d/%d", cmd.commandset, cmd.command);
    error = true;
    return false;
  }

  return true;
}

void Connection::SetupIDSizes()
{
  Command cmd(CommandSet::VirtualMachine, 7);
  if(!SendReceive(cmd))
    return;
{'fraction_non_alphanumeric': 0.1411908314119083, 'fraction_numerical': 0.0078665400786654, 'mean_word_length': 4.089026915113871, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7573245', 'n_tokens_mistral': 2169, 'n_tokens_neox': 2042, 'n_words': 839}