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; } }
/** 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; }; };