void Reconstructor::reconstructSession(Session *s) {
    // We get one monolithic file from a session.  If we have the torrent file
    // we can break it up, otherwise the user will have to do it manually, as we
    // don't have that information.
    File file;
    Torrent *torrent = NULL; // Hold the torrent for this session if we have it

    ip_piece_map_t pieces = s->getPieces();
    std::map<std::string, Peer> peers = s->getPeers();
    std::map<std::string, Peer>::iterator it;
    std::vector<unsigned int>::iterator uit;
    char hash_string[42];
    unsigned char temp_hash[20];
//    std::cout.rdbuf((*(this->ohandle)).rdbuf());

    // Output statistics
    // Make it easier to differentiate between different sessions in output
    std::cout << "****************************************" << std::endl;
    std::cout << "Processing a new BitTorrent session" << std::endl;
    std::cout << "SHA-1 Info Hash: " << std::endl << "\t";
    const char *h = s->getHash().data();
    for (int i = 0; i < 20; i++)
        printf("%x", (unsigned char)h[i]);
    std::cout << std::endl;

    // Build up our file from the session pieces
    ip_piece_map_t::iterator m, me;
    std::vector<Piece*>::iterator p, pe;
    for (m = pieces.begin(), me = pieces.end(); m != me; ++m) {
        for (p = m->second.begin(), pe = m->second.end(); p != pe; ++p) {
            if (not (*p)->isValid()) {
                assert(0 && "Should never have an invalid piece here");
            }
            file.addPiece(*p);
        }
    }

    std::cout << "Peers: " << std::endl;
    //output ip:port for each peer
    for (it = peers.begin(); it != peers.end(); it++) {
        //Only print out active peers
        if (it->second.active) {
            std::cout << "\t" << it->second.ip << ":"
                    << it->second.port << std::endl;
        }
    }

    //output upload statistics(if any)
    for (uit = s->getUploadedIndices().begin();
                    uit != s->getUploadedIndices().end(); uit++) {
            std::cout << "Uploaded part of piece index " << *uit << std::endl;
    }

    std::vector<Torrent*>::iterator i, ie;
    for (i = this->m_torrents.begin(), ie = this->m_torrents.end(); i != ie; ++i) {
//        if ((*i)->info_hash() == s->getHash().data()) {
        if (compare_sha1s((const unsigned char *)(*i)->info_hash().data(),
                          (const unsigned char *)s->getHash().data())) {
            torrent = *i;
        }
    }
    file.reconstructFile(torrent);

    if (torrent == NULL) {
        // We still want to output, just no verification.  Refactor this ASAP
        // Name the file after its checksum
        const unsigned char *data = (const unsigned char*) file.contents().data();
        SHA1(data, file.contents().length(), temp_hash);
        //FIXME This is disgusting
        snprintf(hash_string, 42, "%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x",
                 (unsigned char)temp_hash[0], (unsigned char)temp_hash[1],
                 (unsigned char)temp_hash[2], (unsigned char)temp_hash[3],
                 (unsigned char)temp_hash[4], (unsigned char)temp_hash[5],
                 (unsigned char)temp_hash[6], (unsigned char)temp_hash[7],
                 (unsigned char)temp_hash[8], (unsigned char)temp_hash[9],
                 (unsigned char)temp_hash[10], (unsigned char)temp_hash[11],
                 (unsigned char)temp_hash[12], (unsigned char)temp_hash[13],
                 (unsigned char)temp_hash[14], (unsigned char)temp_hash[15],
                 (unsigned char)temp_hash[16], (unsigned char)temp_hash[17],
                 (unsigned char)temp_hash[18], (unsigned char)temp_hash[19]);
        file.name(hash_string);

        std::cout << "Output filename: " << hash_string << std::endl;

        // We get file.  How are you gentlemen?  Output me to your base.
        std::cout << "Reconstructed file size: "
                  << file.writeFile(0, std::string::npos)
                  << " bytes." << std::endl;

        return;
    }

    // Break up files here
    unsigned int file_offset = 0;
    std::vector<unsigned int> v = torrent->file_lengths();
    for (unsigned int i=0; i < v.size(); ++i) {
        std::string curr_file = file.contents().substr(file_offset, v.at(i));
        // Name the file after its checksum
        const unsigned char *data = (const unsigned char*) curr_file.data();
        SHA1(data, curr_file.length(), temp_hash);
        //FIXME This is disgusting
        snprintf(hash_string, 42, "%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x",
                 (unsigned char)temp_hash[0], (unsigned char)temp_hash[1],
                 (unsigned char)temp_hash[2], (unsigned char)temp_hash[3],
                 (unsigned char)temp_hash[4], (unsigned char)temp_hash[5],
                 (unsigned char)temp_hash[6], (unsigned char)temp_hash[7],
                 (unsigned char)temp_hash[8], (unsigned char)temp_hash[9],
                 (unsigned char)temp_hash[10], (unsigned char)temp_hash[11],
                 (unsigned char)temp_hash[12], (unsigned char)temp_hash[13],
                 (unsigned char)temp_hash[14], (unsigned char)temp_hash[15],
                 (unsigned char)temp_hash[16], (unsigned char)temp_hash[17],
                 (unsigned char)temp_hash[18], (unsigned char)temp_hash[19]);
        file.name(hash_string);

        std::cout << "Output filename: " << hash_string << std::endl;

        // We get file.  How are you gentlemen?  Output me to your base.
        std::cout << "Reconstructed file size: "
                  << file.writeFile(file_offset, v.at(i))
                  << " bytes." << std::endl;

        file_offset += v.at(i);
    }
}