Created
January 10, 2013 09:50
-
-
Save Deepwalker/4500836 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'macaddr' | |
module AngryUID | |
# TODO Now we dont resolve time problems - if | |
# we move time to past, then bad things can happen | |
class UID | |
CLOCK_MULTIPLIER = 10_000_000 # 10ns | |
# Arrange | |
# ------- | |
# tt tt tt tt tt tt tt _ ss __ pp pp _ mm mm mm mm mm mm | |
# tt - time with 10ns precision, 7 bytes | |
# ss - sequence number (not used now), 1 byte | |
# pp - pid, 2 bytes | |
# mm - mac address, 6 bytes | |
def initialize | |
@mac_addr = mac_address | |
@pid = Process.pid | |
@base = (@pid << (6 * 8)) + @mac_addr | |
@seq = 0 | |
@last_time = 0 | |
end | |
def time | |
(Time.now.to_f * CLOCK_MULTIPLIER).to_i | |
end | |
def generate | |
new_time = time | |
if new_time <= @last_time | |
raise 'Pizdec blya' | |
end | |
@last_time = new_time | |
(new_time << (9 * 8)) + @base + (@seq << 8 * 8) | |
end | |
def hex | |
generate.to_s(16) | |
end | |
# From `uuid` gem. | |
# ## | |
# # Generate a pseudo MAC address because we have no pure-ruby way | |
# # to know the MAC address of the NIC this system uses. Note | |
# # that cheating with pseudo arresses here is completely legal: | |
# # see Section 4.5 of RFC4122 for details. | |
# # | |
# # This implementation is shamelessly stolen from | |
# # https://github.com/spectra/ruby-uuid/blob/master/uuid.rb | |
# # Thanks spectra. | |
# # | |
def mac_address | |
iee_mac_address || pseudo_mac_address | |
end | |
def iee_mac_address | |
begin | |
Mac.addr.gsub(/:|-/, '').hex & 0x7FFFFFFFFFFF | |
rescue | |
nil | |
end | |
end | |
def pseudo_mac_address | |
sha1 = ::Digest::SHA1.new | |
256.times do | |
r = [rand(0x100000000)].pack "N" | |
sha1.update r | |
end | |
str = sha1.digest | |
r = rand 14 # 20-6 | |
node = str[r, 6] || str | |
if RUBY_VERSION >= "1.9.0" | |
nnode = node.bytes.to_a | |
nnode[0] |= 0x01 | |
node = '' | |
nnode.each { |s| node << s.chr } | |
else | |
node[0] |= 0x01 # multicast bit | |
end | |
node.bytes.collect{|b|b.to_s(16)}.join.hex & 0x7FFFFFFFFFFF | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment