Example #1
0
bool playturn_network_adapter::read(config& dst)
{
	assert(dst.empty());
	if(is_at_end())
	{
		read_from_network();
	}
	if(is_at_end())
	{
		//that means we couldn't read anything from the network.
		return false;
	}
	//skip empty data.
	while(next_ == data_.begin()->ordered_end())
	{
		data_.pop_front();
		next_ = data_.front().ordered_begin();
		assert(!is_at_end());
	}
	config& child = dst.add_child(next_->key);
	//TODO: implement a non const version of ordered children
	config& child_old = const_cast<config&>(next_->cfg);
	if(next_->key == "turn")
	{
		//split [turn] indo different [turn] for each child.
		assert(next_->cfg.all_children_count() > next_command_num_);
		config::all_children_iterator itor = child_old.ordered_begin();
		//TODO: implement operator + (all_children_iterator, int ) properly
		std::advance(itor, next_command_num_);
		//TODO: implement a non const version of ordered children
		config& childchild_old = const_cast<config&>(itor->cfg);
		config& childchild = child.add_child(itor->key);
		childchild.swap(childchild_old);
		
		++next_command_num_;
		if(next_->cfg.all_children_count() == next_command_num_)
		{
			next_command_num_ = 0;
			++next_;
		}
		return true;
	}
	else
	{
		child.swap(child_old);
		++next_;
		return true;
	}
}
Example #2
0
/** This function handles a single connection */
void handle_connection(int fd) {
  unsigned char key[16];
  char challenge[SIZEOF_CHALLENGE];
  int len;
  int version;
  int length;
  char *filename;
  int target_fd;
  uint32_t calculated_length;
  RC4 rc4;
  uint64_t image_size;
  StringIO queue;

  // Read the challenge:
  len = read(fd, challenge, SIZEOF_CHALLENGE);
  if(len < SIZEOF_CHALLENGE) {
    DEBUG("Unable to read challenge from socket\n");
    return;
  };

  // Try to calculate the session key from this:
  if(!ecc_get_key((char *)key, challenge, Priv)) {
    DEBUG("Unable to decode challenge\n");
    return;
  };
  
  // Prepare the key:
  rc4 = CONSTRUCT(RC4, RC4, Con, NULL, key, sizeof(key));
  queue = CONSTRUCT(StringIO, StringIO, Con, rc4);

  if(!read_from_network(fd, (unsigned char *)&version, sizeof(version), rc4)) {
    DEBUG("Cant read version\n");
    return;
  };
  version = ntohl(version);

  if(version != REMOTE_VERSION) {
    DEBUG("Client version not supported\n");
    return;
  };
  
  if(!read_from_network(fd, (unsigned char *)&length, sizeof(length), rc4))
    return;

  length = ntohl(length);

  // Make sure the filename is not too large
  if(length > 1024) return;

  filename = talloc_zero_size(NULL, length+1);
  if(!read_from_network(fd, (unsigned char *)filename, length, rc4))
    return;

  target_fd = open(filename, O_RDONLY);
  if(target_fd < 0) {
    DEBUG("Cant open %s..\n", filename);
    return;
  };

  //Figure out the image size:
  image_size = lseek(target_fd, 0, SEEK_END);

  while(1) {
    uint64_t offset;
    uint32_t length;
    char buff[BUFF_SIZE];

    if(!read_from_network(fd, (unsigned char *)&offset, sizeof(offset), rc4))
      return;

    offset = ntohll(offset);

    if(!read_from_network(fd, (unsigned char *)&length, sizeof(length), rc4))
      return;

    length = ntohl(length);

    // Send out the total length of the data - which may be less than
    // requested if the image is smaller
    {
      uint32_t c_calc_len;

      calculated_length = min(image_size, offset+length) - offset;
      c_calc_len = htonl(calculated_length);
      queue_for_sending(queue, (unsigned char *)&c_calc_len, sizeof(c_calc_len), rc4);
    };

    if(lseek(target_fd, offset, SEEK_SET) != offset) {
      DEBUG("Unable to seek to %llu\n", offset);
      return;
    };

    //DEBUG("Will need to read %u from %llu\n", calculated_length, offset);

    while(calculated_length > 0) {
      int l = read(target_fd, buff, min(calculated_length, BUFF_SIZE));
      if(l==0) {
	break;
      };
      if(l<0) return;

      queue_for_sending(queue, (unsigned char *)buff, l, rc4);

      // If the queue is too full, we need to flush it
      if(queue->size > 64000)
	if(!write_to_network(fd, queue))
	  return;

      calculated_length -= l;
    };

    if(!write_to_network(fd, queue))
      return;
  };
};