/*!
  \file
  \brief パケットの型定義

  \author Satofumi KAMIMURA

  $Id: Packet.cpp 1000 2009-06-13 22:22:06Z satofumi $
*/

#include "PacketBuffer.h"
#include "PacketUtils.h"

using namespace qrk;


void qrk::PacketControl::send(PacketBuffer& buffer, Clients& clients)
{
  for (Clients::iterator it = clients.begin(); it != clients.end(); ++it) {
    const ClientId& client_id = it->first;
    Connection* client = it->second;

    while (! buffer.empty(client_id)) {
      Packet packet = buffer.pop(client_id);
      send(packet, client);
    }
  }
}


void qrk::PacketControl::receive(PacketBuffer& buffer, Clients& clients)
{
  for (Clients::iterator it = clients.begin(); it != clients.end(); ++it) {

    Packet packet(PacketControl::Length, 0);
    Connection* client = it->second;
    if (! receive(packet, client)) {
      continue;
    }

    const ClientId& client_id = it->first;
    buffer.push(packet, client_id);
  }
}


void qrk::PacketControl::send(const Packet& packet, Connection* client)
{
  client->send(&packet[0], packet.size());
}


bool qrk::PacketControl::receive(Packet& packet, Connection* client)
{
  // １パケット分のデータがあるかを確認
  enum { PacketMinimumLength = 6 };
  size_t readable_size = client->size();
  if (readable_size < PacketMinimumLength) {
    // １パケット分のデータがない
    return false;
  }

  packet.resize(PacketControl::Length, 0);
  client->receive(&packet[0], PacketControl::Length, 0);

  size_t packet_length = packetLength(packet);
  if (readable_size < packet_length) {
    // １パケット分のデータがない場合、読み出したデータを書き戻す
    for (int i = PacketControl::Length - 1; i >= 0; --i) {
      client->ungetc(packet[i]);
    }
    return false;
  }

  // パケットを受信して格納
  size_t left_size = packet_length - PacketControl::Length;
  packet.resize(packet_length);
  client->receive(&packet[PacketControl::Length], left_size, 0);

  return true;
}
