Skip to content

Commit ed34699

Browse files
committed
refactor: move mac generation logic to wire package
1 parent d05a465 commit ed34699

File tree

6 files changed

+59
-56
lines changed

6 files changed

+59
-56
lines changed

packages/tcpip/src/bindings/bridge-interface.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
generateMacAddress,
23
parseIPv4Address,
34
parseMacAddress,
45
serializeIPv4Cidr,
@@ -8,7 +9,7 @@ import {
89
type MacAddress,
910
} from '@tcpip/wire';
1011
import type { Pointer } from '../types.js';
11-
import { generateMacAddress, Hooks } from '../util.js';
12+
import { Hooks } from '../util.js';
1213
import { Bindings } from './base.js';
1314
import { tapInterfaceHooks, type TapInterface } from './tap-interface.js';
1415

packages/tcpip/src/bindings/tap-interface.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
generateMacAddress,
23
parseIPv4Address,
34
parseMacAddress,
45
serializeIPv4Cidr,
@@ -12,7 +13,6 @@ import type { Pointer } from '../types.js';
1213
import {
1314
ExtendedReadableStream,
1415
fromReadable,
15-
generateMacAddress,
1616
Hooks,
1717
nextMicrotask,
1818
} from '../util.js';

packages/tcpip/src/util.test.ts

Lines changed: 0 additions & 30 deletions
This file was deleted.

packages/tcpip/src/util.ts

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -215,23 +215,3 @@ export class ExtendedReadableStream<R> extends ReadableStream<R> {
215215
export async function nextMicrotask() {
216216
return await new Promise<void>((resolve) => queueMicrotask(resolve));
217217
}
218-
219-
/**
220-
* Generates a random MAC address.
221-
*
222-
* The generated address is locally administered (so won't conflict
223-
* with real devices) and unicast (so it can be used as a source address).
224-
*/
225-
export function generateMacAddress() {
226-
const mac = new Uint8Array(6);
227-
crypto.getRandomValues(mac);
228-
229-
// Control bits only apply to the first byte
230-
mac[0] =
231-
// Clear the 2 least significant bits
232-
(mac[0]! & 0b11111100) |
233-
// Set locally administered bit (bit 1) to 1 and unicast bit (bit 0) to 0
234-
0b00000010;
235-
236-
return mac;
237-
}

packages/wire/src/ethernet.test.ts

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1-
import { describe, expect, test } from 'vitest';
2-
import { parseMacAddress, serializeMacAddress } from './ethernet.js';
1+
import { describe, expect, test, vi } from 'vitest';
2+
import {
3+
generateMacAddress,
4+
parseMacAddress,
5+
serializeMacAddress,
6+
} from './ethernet.js';
37

4-
describe('parseMacAddress', () => {
8+
describe('serialize mac', () => {
59
test('should parse a valid MAC address string into a Uint8Array', () => {
610
const macString = '01:23:45:67:89:ab';
711
const result = serializeMacAddress(macString);
@@ -29,7 +33,7 @@ describe('parseMacAddress', () => {
2933
});
3034
});
3135

32-
describe('formatMacAddress', () => {
36+
describe('parse mac', () => {
3337
test('should format a valid Uint8Array into a MAC address string', () => {
3438
const macArray = new Uint8Array([0x01, 0x23, 0x45, 0x67, 0x89, 0xab]);
3539
const result = parseMacAddress(macArray);
@@ -65,3 +69,31 @@ describe('formatMacAddress', () => {
6569
expect(result).toBe('ff:ff:ff:ff:ff:ff');
6670
});
6771
});
72+
73+
describe('generate mac', () => {
74+
test('should generate a MAC address of length 6', () => {
75+
const mac = generateMacAddress();
76+
expect(mac).toHaveLength(6);
77+
});
78+
79+
test('should set the locally administered bit and clear the unicast bit', () => {
80+
const mac = generateMacAddress();
81+
// Check that the locally administered bit (bit 1) is set to 1
82+
expect(mac[0]! & 0b00000010).toBe(0b00000010);
83+
// Check that the unicast bit (bit 0) is set to 0
84+
expect(mac[0]! & 0b00000001).toBe(0b00000000);
85+
});
86+
87+
test('should generate different MAC addresses on subsequent calls', () => {
88+
const mac1 = generateMacAddress();
89+
const mac2 = generateMacAddress();
90+
expect(mac1).not.toEqual(mac2);
91+
});
92+
93+
test('should use crypto.getRandomValues to generate the MAC address', () => {
94+
const spy = vi.spyOn(crypto, 'getRandomValues');
95+
generateMacAddress();
96+
expect(spy).toHaveBeenCalled();
97+
spy.mockRestore();
98+
});
99+
});

packages/wire/src/ethernet.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,26 @@ export function serializeMacAddress(mac: string) {
125125
);
126126
}
127127

128+
/**
129+
* Generates a random MAC address.
130+
*
131+
* The generated address is locally administered (so won't conflict
132+
* with real devices) and unicast (so it can be used as a source address).
133+
*/
134+
export function generateMacAddress() {
135+
const mac = new Uint8Array(6);
136+
crypto.getRandomValues(mac);
137+
138+
// Control bits only apply to the first byte
139+
mac[0] =
140+
// Clear the 2 least significant bits
141+
(mac[0]! & 0b11111100) |
142+
// Set locally administered bit (bit 1) to 1 and unicast bit (bit 0) to 0
143+
0b00000010;
144+
145+
return mac;
146+
}
147+
128148
/**
129149
* Parses an Ethernet type into a string.
130150
*/

0 commit comments

Comments
 (0)