MobDev.DistCookie (mob_dev v0.7.21)

Copy Markdown View Source

The private distribution cookie for a project's development builds.

One random 256-bit cookie per app (keyed by its bundle id), shared by iOS, Android and the Mac-side node, so concurrent mob.connect sessions attach without restarting the app under different credentials. It lives in an owner-only directory under ~/.mob/dist_cookies/, reaches the app only at deploy/launch time, and is never printed. Deploy also writes it to mob_dist_cookie in the app's beams directory (write_app_file!/2), where the app reads it at boot, so a relaunch outside mob_dev keeps it. A hand-started node loads it with Node.set_cookie(MobDev.DistCookie.for_project!()) from the project, which keeps it out of process arguments (--cookie would show it in ps).

Apps built against a mob from before MOB-49 still answer to the public :mob_secret. Without an explicit cookie, connect/2 tries the private cookie first and falls back to that legacy one with a warning, so existing apps stay reachable until they are redeployed.

Summary

Functions

Name of the cookie file in an app's beams directory. Android's Mob.Dist and iOS's mob_beam.m read $MOB_BEAMS_DIR/mob_dist_cookie at boot when the launch environment carries no cookie.

Cookies to try against a device node, in order.

Connects to node, trying each cookie in cookies in order.

Returns the private cookie for the current project, creating it on first use.

Validates an explicit cookie given on the command line.

Writes cookie to dir/mob_dist_cookie, owner-only, and returns the path.

Functions

app_file()

@spec app_file() :: String.t()

Name of the cookie file in an app's beams directory. Android's Mob.Dist and iOS's mob_beam.m read $MOB_BEAMS_DIR/mob_dist_cookie at boot when the launch environment carries no cookie.

candidates(explicit \\ nil, loader \\ &for_project!/0)

@spec candidates(atom() | String.t() | nil, (-> atom())) :: [atom(), ...]

Cookies to try against a device node, in order.

An explicit cookie (--cookie) is the only candidate. Without one, the project's private cookie comes first and the legacy public cookie second. The first entry is also the right default cookie for the Mac-side node.

connect(node, cookies)

@spec connect(node(), [atom(), ...]) :: {:ok, atom()} | :error

Connects to node, trying each cookie in cookies in order.

Returns {:ok, cookie} with the cookie that worked. An already connected node answers with the cookie it was connected under, untouched: OTP reports an existing connection as success without a handshake, so trying a candidate on it would prove nothing and overwrite the cookie that did authenticate. When no cookie works, the node's cookie is reset to the first candidate: a per-node cookie also authenticates incoming connections claiming that name, so the legacy public cookie must not stay set for a node that did not need it.

for_project!()

@spec for_project!() :: atom()

Returns the private cookie for the current project, creating it on first use.

parse!(cookie)

@spec parse!(atom() | String.t()) :: atom()

Validates an explicit cookie given on the command line.

write_app_file!(dir, cookie)

@spec write_app_file!(String.t(), atom()) :: String.t()

Writes cookie to dir/mob_dist_cookie, owner-only, and returns the path.

For directories on this Mac that an app reads its BEAMs from: the iOS simulator runtime dir, or the staging dir a physical-iPhone deploy copies to the device. The cookie is written inside a fresh 0700 directory, made 0600, then renamed over any previous file: nobody else can open it at any point (a descriptor opened on the parent before the chmod doesn't help, since lookups check the directory's current mode), and a booting app never sees half a file.