-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This is a trivial cache that speeds up reads and the slow genkey call to return the public key. It's invalidated by nearly everything. In practice, though, normal operation is readonly and writes are only at provisioning time. Fixes #16
- Loading branch information
Showing
3 changed files
with
151 additions
and
22 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
defmodule ATECC508A.Transport.Cache do | ||
@moduledoc """ | ||
Simple cache for reducing unnecessary traffic to the ATECC508A | ||
""" | ||
|
||
@type state() :: map() | ||
|
||
@atecc508a_op_read 0x02 | ||
@atecc508a_op_genkey 0x40 | ||
@atecc508a_op_random 0x1B | ||
|
||
@doc """ | ||
Initialize the cache for one ATECC508A | ||
""" | ||
@spec init() :: state() | ||
def init() do | ||
%{} | ||
end | ||
|
||
@doc """ | ||
Check if the specified request is in the cache | ||
""" | ||
@spec get(state(), binary()) :: binary() | nil | ||
def get(cache, request) do | ||
Map.get(cache, request) | ||
end | ||
|
||
@doc """ | ||
Save a response back to the cache | ||
""" | ||
@spec put(state, binary(), any()) :: state() | ||
|
||
# Cache all reads | ||
def put(cache, <<@atecc508a_op_read, _::binary>> = request, response) do | ||
Map.put(cache, request, response) | ||
end | ||
|
||
# Cache the response to getting a public key | ||
def put(cache, <<@atecc508a_op_genkey, 0, _key_id::little-16>> = request, response) do | ||
Map.put(cache, request, response) | ||
end | ||
|
||
# Don't cache random numbers | ||
def put(cache, <<@atecc508a_op_random, _::binary>>, _response), do: cache | ||
|
||
# Flush the cache on everything else: | ||
# writes, locks, etc. | ||
# | ||
# This is overkill, but safe. | ||
def put(_cache, _request, _response), do: %{} | ||
end |
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
defmodule ATECC508A.Transport.CacheTest do | ||
use ExUnit.Case | ||
|
||
alias ATECC508A.Transport.Cache | ||
|
||
test "caches reads" do | ||
req = <<2, 0, 0, 0>> | ||
resp = {:ok, <<1>>} | ||
|
||
cache = Cache.init() | ||
assert Cache.get(cache, req) == nil | ||
|
||
cache = Cache.put(cache, req, resp) | ||
assert Cache.get(cache, req) == resp | ||
end | ||
|
||
test "cache genkey public key calculation " do | ||
req = <<0x40, 0, 1, 0>> | ||
resp = {:ok, <<1, 2, 3, 4, 5>>} | ||
|
||
cache = Cache.init() | ||
assert Cache.get(cache, req) == nil | ||
|
||
cache = Cache.put(cache, req, resp) | ||
assert Cache.get(cache, req) == resp | ||
end | ||
|
||
test "doesn't cache genkey creation" do | ||
req = <<0x40, 1, 1, 0>> | ||
resp = {:ok, <<1, 2, 3, 4, 5>>} | ||
|
||
cache = Cache.init() | ||
assert Cache.get(cache, req) == nil | ||
|
||
cache = Cache.put(cache, req, resp) | ||
assert Cache.get(cache, req) == nil | ||
end | ||
|
||
test "writes clear the cache" do | ||
read_req = <<2, 0, 0, 0>> | ||
write_req = <<0x12, 0, 0, 0>> | ||
resp = {:ok, <<1>>} | ||
|
||
cache = Cache.init() | ||
assert Cache.get(cache, read_req) == nil | ||
|
||
cache = Cache.put(cache, read_req, resp) | ||
assert Cache.get(cache, read_req) == resp | ||
|
||
cache = Cache.put(cache, write_req, resp) | ||
assert cache == %{} | ||
end | ||
end |