blob: f19eda75704c9354432bc4e4ceed0e80c3a9e196 [file] [log] [blame]
// Copyright 2013 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Author: jmaessen@google.com (Jan-Willem Maessen)
#include "pagespeed/kernel/util/hashed_nonce_generator.h"
#include <unistd.h>
#include "base/logging.h"
#include "pagespeed/kernel/base/basictypes.h"
#include "pagespeed/kernel/base/hasher.h"
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/util/nonce_generator.h"
namespace net_instaweb {
HashedNonceGenerator::HashedNonceGenerator(
const Hasher* hasher, StringPiece key, AbstractMutex* mutex)
: NonceGenerator(mutex),
hasher_(hasher),
key_size_(key.size() - sizeof(counter_)) {
DCHECK_LE(2 * hasher->RawHashSizeInBytes(), static_cast<int>(key.size()));
// Allocate enough space in key_ to hold future data for hashing. Note in
// particular that we use the last sizeof(counter_) bits of the passed in key
// to initialize counter_, and thus exclude it from key_size_. But we will
// ultimately need to buffer the initial key_size_ bytes of the passed-in key,
// the counter_, and the pid.
char *key_data = new char[key_size_ + sizeof(counter_) + sizeof(pid_t)];
memcpy(key_data, key.data(), key_size_);
memcpy(&counter_, key.data() + key_size_, sizeof(counter_));
key_.reset(key_data);
counter_ = hasher_->HashToUint64(key);
}
HashedNonceGenerator::~HashedNonceGenerator() { }
uint64 HashedNonceGenerator::NewNonceImpl() {
++counter_;
// We look up the pid here and include it because we may have forked since
// this HashedNonceGenerator was created, and we want to make sure the forked
// values yield distinct nonce streams.
pid_t pid = getpid();
// We append data to key_, then hash the whole buffer.
memcpy(&key_[key_size_], &counter_, sizeof(counter_));
memcpy(&key_[key_size_ + sizeof(counter_)], &pid, sizeof(pid));
return hasher_->HashToUint64(
StringPiece(key_.get(), key_size_ + sizeof(counter_) + sizeof(pid)));
}
} // namespace net_instaweb