Skip to content

Commit

Permalink
Support random setup codes and saved verifiers
Browse files Browse the repository at this point in the history
commit 3882b2b
Author: Samuel Elliott <samuel@fancy.org.uk>
Date:   Mon Nov 2 21:21:30 2020 +0000

    Fix CI tests

commit 5e06e26
Merge: d2a1fbc 977d5ad
Author: Samuel Elliott <samuel@fancy.org.uk>
Date:   Mon Nov 2 20:52:55 2020 +0000

    Merge remote-tracking branch 'KhaosT/beta' into random-setup-codes

    # Conflicts:
    #	src/lib/Accessory.ts
    #	src/lib/Advertiser.ts
    #	src/lib/HAPServer.ts
    #	src/lib/util/eventedhttp.ts

commit d2a1fbc
Merge: 130d5d6 d70a1ba
Author: Samuel Elliott <samuel@fancy.org.uk>
Date:   Mon Nov 2 19:27:50 2020 +0000

    Merge remote-tracking branch 'KhaosT/master' into random-setup-codes

    # Conflicts:
    #	src/lib/Accessory.ts
    #	src/lib/Advertiser.ts
    #	src/lib/util/eventedhttp.ts

commit 130d5d6
Author: Samuel Elliott <samuel@fancy.org.uk>
Date:   Mon Nov 2 19:18:42 2020 +0000

    Support saved verifiers

commit 60a52f7
Author: Samuel Elliott <samuel@fancy.org.uk>
Date:   Mon Nov 2 18:59:09 2020 +0000

    Move setup ID related functions

commit 0903a20
Author: Samuel Elliott <samuel@fancy.org.uk>
Date:   Mon Nov 2 18:14:55 2020 +0000

    Refactor using async/await

commit 3d9ce22
Author: Samuel Elliott <samuel@fancy.org.uk>
Date:   Mon Nov 2 17:09:46 2020 +0000

    Print a warning when a pair request is rejected due to the attempt limit

commit 5329ff4
Merge: f6c89db 5cacbd4
Author: Samuel Elliott <samuel@fancy.org.uk>
Date:   Mon Nov 2 16:56:24 2020 +0000

    Merge remote-tracking branch 'KhaosT/master' into random-setup-codes

    # Conflicts:
    #	src/CameraCore.ts
    #	src/lib/Accessory.ts
    #	src/lib/HAPServer.ts
    #	src/lib/model/AccessoryInfo.ts
    #	src/lib/util/eventedhttp.ts

commit 977d5ad
Author: Supereg <mail@anderl-bauer.de>
Date:   Tue Oct 20 13:54:59 2020 +0200

    Adjust idle timeout configuration

commit 46c6498
Author: Supereg <mail@anderl-bauer.de>
Date:   Tue Oct 20 13:34:34 2020 +0200

    Adding idle timeout to hap connections

commit 80ef334
Author: Supereg <mail@anderl-bauer.de>
Date:   Tue Oct 20 10:29:11 2020 +0200

    Fixed accessory characteristic-warning event signature

commit 77a2042
Author: Supereg <mail@anderl-bauer.de>
Date:   Tue Oct 20 10:22:01 2020 +0200

    Pass more characteristic warnings through the event system for homebridge

commit a7d2c5b
Author: Supereg <mail@anderl-bauer.de>
Date:   Tue Oct 20 02:21:29 2020 +0200

    Correctly transform 0 and 1 to boolean values

commit 8234e7b
Author: Supereg <mail@anderl-bauer.de>
Date:   Tue Oct 20 02:21:16 2020 +0200

    Force http socket to connect to loopback address

commit 14a6424
Author: Supereg <mail@anderl-bauer.de>
Date:   Tue Oct 20 02:16:56 2020 +0200

    Adding unit tests for net-utils

commit bc24a23
Author: Supereg <mail@anderl-bauer.de>
Date:   Mon Oct 19 15:02:05 2020 +0200

    Only fire characteristic change when value actually changed

commit 0a45bbf
Author: Supereg <mail@anderl-bauer.de>
Date:   Mon Oct 19 02:19:44 2020 +0200

    Removed notify perms from Version characteristic again.
    Additional Authorization should not be added by default.

commit 581298f
Author: Supereg <mail@anderl-bauer.de>
Date:   Mon Oct 19 01:47:41 2020 +0200

    Don't set the value before calling the set handler

commit 9b6a3ce
Author: Supereg <mail@anderl-bauer.de>
Date:   Mon Oct 19 00:29:20 2020 +0200

    Fixed connection debug output

commit 362a5eb
Author: Supereg <mail@anderl-bauer.de>
Date:   Mon Oct 19 00:12:03 2020 +0200

    Use the correct subclass when deserializing characteristics and services from disk

commit 75452d7
Author: Supereg <mail@anderl-bauer.de>
Date:   Sun Oct 18 22:42:31 2020 +0200

    Add deprecated CameraControl service again

commit 1b47a4c
Author: Supereg <mail@anderl-bauer.de>
Date:   Sun Oct 18 20:19:44 2020 +0200

    Adding debug output for current connection state every minute

commit 091e2a4
Author: Supereg <mail@anderl-bauer.de>
Date:   Fri Oct 16 23:23:07 2020 +0200

    Reworked characteristic and service definition generation

commit 5e9d970
Author: Supereg <mail@anderl-bauer.de>
Date:   Wed Oct 14 16:26:17 2020 +0200

    Improve default value handling of AccessoryInformation characteristics
    Removed error thrown when setting undefined

commit 7fde47b
Author: Supereg <mail@anderl-bauer.de>
Date:   Tue Oct 13 23:32:54 2020 +0200

    Improved handling of undefined and null values for AccessoryInformation service

commit 8fe0b15
Author: Supereg <mail@anderl-bauer.de>
Date:   Tue Oct 13 16:39:38 2020 +0200

    Make warnings less dramatic

commit 917fa6a
Author: Supereg <mail@anderl-bauer.de>
Date:   Mon Oct 12 23:24:58 2020 +0200

    Adding ability to track code coverage

commit e329727
Author: Supereg <mail@anderl-bauer.de>
Date:   Mon Oct 12 22:29:22 2020 +0200

    Fixed assertions and tests

commit 9b30452
Author: Supereg <mail@anderl-bauer.de>
Date:   Mon Oct 12 22:25:04 2020 +0200

    Improved some typing. Only assignIds on main accessory

commit c8b5791
Author: Supereg <mail@anderl-bauer.de>
Date:   Mon Oct 12 15:15:17 2020 +0200

    Minor adjustments handling promise errors on characteristic handlers.
    Additionally we added a custom try-catch for the validateInput function to print a more meaningful error message

commit 83804fb
Author: oznu <dev@oz.nu>
Date:   Mon Oct 12 23:48:00 2020 +1100

    Add support for promise based Characteristic setters and getters (homebridge#849)

commit 3f59de2
Author: Supereg <mail@anderl-bauer.de>
Date:   Mon Oct 12 14:39:42 2020 +0200

    Mitigate crash when check accessory configuration and aid/iids aren't set yet

commit 9d63614
Author: Supereg <mail@anderl-bauer.de>
Date:   Fri Oct 9 00:27:08 2020 +0200

    Ignore empty bind option

commit ac57c4d
Author: Supereg <mail@anderl-bauer.de>
Date:   Fri Oct 9 00:09:51 2020 +0200

    Adjust the bind option to always bind on unspecified addresses to keep a socket on the loopback address for config-ui

commit 6f6a971
Author: Supereg <mail@anderl-bauer.de>
Date:   Thu Oct 8 23:26:53 2020 +0200

    Fix event delivery for bridged accessories

commit 0bedbc5
Author: Supereg <mail@anderl-bauer.de>
Date:   Thu Oct 8 18:28:10 2020 +0200

    Prevent that SerialNumber or Model gets a value assigned with length less or equal to 1 character (fixes homebridge#824)

    Otherwise HomeKit will reject the whole accessory!

commit 5f8a827
Author: Supereg <mail@anderl-bauer.de>
Date:   Thu Oct 8 18:05:31 2020 +0200

    Return http error when receiving duplicate values in /characteristics set/get requests

commit 0ac698f
Author: Supereg <mail@anderl-bauer.de>
Date:   Thu Oct 8 17:45:47 2020 +0200

    Mute event notification calls when aid/iid are not yet set
    Catch any errors which may occur when sending events

commit 7073a82
Author: Supereg <mail@anderl-bauer.de>
Date:   Thu Oct 8 05:52:14 2020 +0200

    Fixed bridged accessories not being returned on /accessories request

commit 4a3f9e7
Author: Supereg <mail@anderl-bauer.de>
Date:   Thu Oct 8 05:30:32 2020 +0200

    Fixed adding bridged accessories

commit 7deb450
Author: Supereg <mail@anderl-bauer.de>
Date:   Thu Oct 8 05:20:38 2020 +0200

    Ensure timeouts don't prevent shutdown

commit df0761d
Author: Supereg <mail@anderl-bauer.de>
Date:   Thu Oct 8 05:15:25 2020 +0200

    Boolean values for numeric formats are now properly converted

commit 074ede1
Author: Supereg <mail@anderl-bauer.de>
Date:   Thu Oct 8 05:14:59 2020 +0200

    Debounce current configuration number increments

commit 2d7aaba
Author: Supereg <mail@anderl-bauer.de>
Date:   Thu Oct 8 04:18:42 2020 +0200

    Service code cleanup

commit 7f00b15
Author: Supereg <mail@anderl-bauer.de>
Date:   Thu Oct 8 04:05:54 2020 +0200

    * Reworked input validation for characteristic values and properties
    * Send correct -70410 response when receiving invalid value in request (out of range etc)
    * GET handler is now called on /accessories to have latest value on discover
    * Added more documentation

commit a063bc1
Author: Supereg <mail@anderl-bauer.de>
Date:   Tue Oct 6 16:40:50 2020 +0200

    Fixing tests

commit 50be234
Author: Supereg <mail@anderl-bauer.de>
Date:   Tue Oct 6 16:06:52 2020 +0200

    setValue method will now fire a SET event again

commit e16a3e4
Author: Supereg <mail@anderl-bauer.de>
Date:   Tue Oct 6 01:10:15 2020 +0200

    Fix tests

commit 89ad4ac
Author: Supereg <mail@anderl-bauer.de>
Date:   Tue Oct 6 00:59:29 2020 +0200

    Remove last traces of custom EventEmitter type

commit f908a9e
Author: Supereg <mail@anderl-bauer.de>
Date:   Tue Oct 6 00:28:25 2020 +0200

    Fixed awfully wrong uuids for iOS 14 characteristics and services

commit 73bf81c
Author: Supereg <mail@anderl-bauer.de>
Date:   Tue Oct 6 00:27:56 2020 +0200

    Adding timeouts to SET, GET and image request handlers.
    Some minor code cleanup.

commit 3673c8d
Author: Supereg <mail@anderl-bauer.de>
Date:   Mon Oct 5 19:22:03 2020 +0200

    Adding support for additional authorization data to be checked by custom handler

commit 024b021
Author: Supereg <mail@anderl-bauer.de>
Date:   Mon Oct 5 18:38:23 2020 +0200

    Minor code fixes in the AccessoryLoader

commit 45b63a7
Author: Supereg <mail@anderl-bauer.de>
Date:   Mon Oct 5 18:24:07 2020 +0200

    Some code cleanup regarding the HAPEncryption object

commit 9f3887d
Author: Supereg <mail@anderl-bauer.de>
Date:   Mon Oct 5 18:10:35 2020 +0200

    Properly delay and combine event notifications

commit d765118
Author: Supereg <mail@anderl-bauer.de>
Date:   Mon Oct 5 16:40:40 2020 +0200

    Bump beta to 0.9.0

commit 8f2c80a
Author: Supereg <mail@anderl-bauer.de>
Date:   Mon Oct 5 01:35:39 2020 +0200

    Removed some obsolete @ts-expect-error

commit 2ef51cf
Author: Supereg <mail@anderl-bauer.de>
Date:   Mon Oct 5 01:31:47 2020 +0200

    Major code cleanup in the EventedHTTPServer and HAPServer classes
    Various fixes, improved typing and more robustness

commit 576271b
Author: Supereg <mail@anderl-bauer.de>
Date:   Sat Oct 3 19:05:35 2020 +0200

    Reduce daysUntilStale to 23

commit 2b57017
Author: Supereg <mail@anderl-bauer.de>
Date:   Sat Oct 3 19:03:08 2020 +0200

    Set the tcp_keepalive_time to 5 seconds

commit 8521c69
Author: Supereg <mail@anderl-bauer.de>
Date:   Sat Oct 3 19:02:46 2020 +0200

    Validate controllerKeySalt length before passing it to the DataStream Server

commit bda16db
Author: Supereg <mail@anderl-bauer.de>
Date:   Wed Sep 30 01:54:05 2020 +0200

    Fixed some tests

commit e2ffbd8
Author: Supereg <mail@anderl-bauer.de>
Date:   Wed Sep 30 01:35:11 2020 +0200

    Completely reworked /characteristics
    * Adding support for metadata, events, type, perms query parameters
    * Moving to promises
    * Reworked Characteristic code

commit 1a6d30b
Author: Supereg <mail@anderl-bauer.de>
Date:   Thu Sep 24 00:54:19 2020 +0200

    Minor improvment of removeLinkedService from Service class

commit 62348d3
Author: Supereg <mail@anderl-bauer.de>
Date:   Thu Sep 24 00:54:07 2020 +0200

    Fixed removeLinkedService

commit c06dbb8
Author: Supereg <mail@anderl-bauer.de>
Date:   Wed Sep 23 19:44:40 2020 +0200

    Listen on the loopback interface only for the internal http server

commit b9b95d5
Author: Supereg <mail@anderl-bauer.de>
Date:   Wed Sep 23 19:14:07 2020 +0200

    Fixed: if a service is removed it is now ensured that no existing services still link to that removed service

commit 72baab0
Author: Supereg <mail@anderl-bauer.de>
Date:   Wed Sep 23 18:59:22 2020 +0200

    Throw a proper exception if chacha20-poly1305 cipher isn't found

commit e858e39
Author: Supereg <mail@anderl-bauer.de>
Date:   Wed Sep 23 18:26:16 2020 +0200

    Minor code cleanup

commit 0843e2a
Author: Supereg <mail@anderl-bauer.de>
Date:   Wed Sep 23 17:53:56 2020 +0200

    Introducing new "bind" publish option, in oder to bind/advertise the hap-nodejs to a certain interface(s)/ip address(es)

commit 5eabcf8
Author: Supereg <mail@anderl-bauer.de>
Date:   Mon Sep 21 15:47:18 2020 +0200

    Mitigating warning for memory leak on the UNPAIRED event

commit 1fa08d0
Author: Supereg <mail@anderl-bauer.de>
Date:   Mon Sep 21 15:39:47 2020 +0200

    Add some little deprecation notice

commit 0afceab
Author: Supereg <mail@anderl-bauer.de>
Date:   Mon Sep 21 15:37:38 2020 +0200

    Adding source-map-support for better stack strace translation

commit 8ee8888
Author: Supereg <mail@anderl-bauer.de>
Date:   Mon Sep 21 15:13:30 2020 +0200

    Notify active streaming session that the application is about to exit

commit 059def9
Author: Supereg <mail@anderl-bauer.de>
Date:   Mon Sep 21 14:59:53 2020 +0200

    Updated service and characteristic definitions to latest iOS 14 release

commit eb9dd8a
Author: Supereg <mail@anderl-bauer.de>
Date:   Mon Sep 21 14:56:15 2020 +0200

    Adding version note to some of the latest characteristics and services

commit 52f61fd
Author: Supereg <mail@anderl-bauer.de>
Date:   Mon Sep 21 14:42:07 2020 +0200

    Doing a subnet check as fallback if local interface detection fails for HAP socket

commit 00bf51d
Author: Supereg <mail@anderl-bauer.de>
Date:   Mon Sep 21 14:20:30 2020 +0200

    Mark the start of beta 0.8.3

commit f6c89db
Author: Samuel Elliott <samuel@fancy.org.uk>
Date:   Sun Apr 12 02:42:33 2020 +0100

    Redo flag checks closer to the spec., add initial transient pair setup support

commit a9dc408
Author: Samuel Elliott <samuel@fancy.org.uk>
Date:   Sun Apr 12 00:54:32 2020 +0100

    Fix checking if another client is trying to pair

commit c436563
Merge: 4abd809 9e86970
Author: Samuel Elliott <samuel@fancy.org.uk>
Date:   Sat Apr 11 19:07:53 2020 +0100

    Merge remote-tracking branch 'KhaosT/master' into random-setup-codes

    # Conflicts:
    #	src/lib/Accessory.ts
    #	src/lib/HAPServer.ts

commit 4abd809
Merge: b4d95e8 6fbafa8
Author: Samuel Elliott <samuel@fancy.org.uk>
Date:   Thu Nov 28 14:07:31 2019 +0000

    Merge remote-tracking branch 'refs/remotes/KhaosT/master' into random-setup-codes

    # Conflicts:
    #	src/lib/Accessory.ts
    #	src/lib/gen/importAsClasses.ts

commit b4d95e8
Merge: f5e303f 50ac924
Author: Samuel Elliott <samuel@fancy.org.uk>
Date:   Sun Nov 3 20:02:45 2019 +0000

    Merge remote-tracking branch 'KhaosT/master' into random-setup-codes

    # Conflicts:
    #	src/lib/HAPServer.ts
    #	src/lib/util/eventedhttp.ts

commit f5e303f
Author: Samuel Elliott <samuel@fancy.org.uk>
Date:   Mon Oct 28 14:06:50 2019 +0000

    Use random setup codes by default and add pair setup start/finish events

commit 0850c5c
Author: Samuel Elliott <samuel@fancy.org.uk>
Date:   Sun Oct 27 22:04:44 2019 +0000

    Use random setup codes in Bridged/CameraCore.ts and only for accessories without a setup code in Core.ts

commit 6830baa
Author: Samuel Elliott <samuel@fancy.org.uk>
Date:   Sun Oct 27 19:57:22 2019 +0000

    Add a function to generate a random setup code

commit a6a4810
Author: Samuel Elliott <samuel@fancy.org.uk>
Date:   Sun Oct 27 19:53:31 2019 +0000

    Support using a random setup code

commit 322baca
Author: Samuel Elliott <samuel@fancy.org.uk>
Date:   Sun Oct 27 18:47:32 2019 +0000

    Fix pairing, unpairing and pairing again without restarting

commit 5babe40
Author: Samuel Elliott <samuel@fancy.org.uk>
Date:   Sun Oct 27 18:02:49 2019 +0000

    Only allow a single pair request
  • Loading branch information
samuelthomas2774 committed Nov 28, 2020
1 parent c2e0451 commit bf825fc
Show file tree
Hide file tree
Showing 12 changed files with 363 additions and 114 deletions.
2 changes: 2 additions & 0 deletions package.json
Expand Up @@ -48,6 +48,8 @@
"README.md",
"LICENSE",
"dist",
"!dist/accessories",
"!dist/scripts",
"@types"
],
"dependencies": {
Expand Down
3 changes: 1 addition & 2 deletions src/BridgedCore.ts
Expand Up @@ -2,7 +2,7 @@ import path from 'path';

import storage from 'node-persist';

import { Accessory, AccessoryEventTypes, AccessoryLoader, Bridge, Categories, uuid, VoidCallback } from './';
import { Accessory, AccessoryEventTypes, AccessoryLoader, Bridge, Categories, uuid, generateSetupCode, VoidCallback } from './';

console.log("HAP-NodeJS starting...");

Expand Down Expand Up @@ -34,7 +34,6 @@ accessories.forEach((accessory: Accessory) => {
bridge.publish({
username: "CC:22:3D:E3:CE:F6",
port: 51826,
pincode: "031-45-154",
category: Categories.BRIDGE
});

Expand Down
8 changes: 2 additions & 6 deletions src/Core.ts
Expand Up @@ -2,7 +2,8 @@ import path from 'path';

import storage from 'node-persist';

import { AccessoryLoader } from './';
import { AccessoryLoader, generateSetupCode } from './';
import { NodeCallback } from './types';

console.log("HAP-NodeJS starting...");

Expand All @@ -28,11 +29,6 @@ accessories.forEach((accessory) => {
throw new Error("Username not found on accessory '" + accessory.displayName +
"'. Core.js requires all accessories to define a unique 'username' property.");

// @ts-ignore
if (!accessory.pincode)
throw new Error("Pincode not found on accessory '" + accessory.displayName +
"'. Core.js requires all accessories to define a 'pincode' property.");

// publish this Accessory on the local network
accessory.publish({
port: targetPort++,
Expand Down
2 changes: 2 additions & 0 deletions src/index.ts
Expand Up @@ -22,6 +22,8 @@ export * from './lib/controller';

export * from './lib/util/clone';
export * from './lib/util/once';
export * from './lib/util/setupcode';
export * from './lib/util/setupid';
export * from './lib/util/tlv';
export * from './lib/util/hapStatusError';
export * from './lib/util/color-utils';
Expand Down
101 changes: 49 additions & 52 deletions src/lib/Accessory.ts
Expand Up @@ -28,6 +28,7 @@ import {
Nullable,
VoidCallback,
WithUUID,
NodeCallback,
} from '../types';
import { Advertiser, AdvertiserEvent } from './Advertiser';
// noinspection JSDeprecatedSymbols
Expand Down Expand Up @@ -59,11 +60,12 @@ import {
IdentifyCallback,
ListPairingsCallback,
PairCallback,
PairIdentity,
ReadCharacteristicsCallback,
RemovePairingCallback,
ResourceRequestCallback,
TLVErrorCode,
WriteCharacteristicsCallback
WriteCharacteristicsCallback,
} from './HAPServer';
import { AccessoryInfo, PermissionTypes } from './model/AccessoryInfo';
import { ControllerStorage } from "./model/ControllerStorage";
Expand All @@ -74,7 +76,10 @@ import { EventName, HAPConnection, HAPUsername } from "./util/eventedhttp";
import { formatOutgoingCharacteristicValue } from "./util/request-util";
import * as uuid from "./util/uuid";
import { toShortForm } from "./util/uuid";
import { generateSetupId, generateSetupUri } from './util/setupid';
import { generateSetupCode } from './util/setupcode';
import Timeout = NodeJS.Timeout;
import { Identity } from 'fast-srp-hap';

const debug = createDebug('HAP-NodeJS:Accessory');
const MAX_ACCESSORIES = 149; // Maximum number of bridged accessories per bridge.
Expand Down Expand Up @@ -168,7 +173,9 @@ export type CharacteristicEvents = Record<string, any>;

export interface PublishInfo {
username: MacAddress;
pincode: HAPPincode;
pincode?: HAPPincode
| ((callback: NodeCallback<string>, connection: HAPConnection) => void)
| {salt: Buffer; verifier: Buffer};
/**
* Specify the category for the HomeKit accessory.
* The category is used only in the mdns advertisement and specifies the devices type
Expand Down Expand Up @@ -263,6 +270,8 @@ const enum WriteRequestState {
TIMED_WRITE_REJECTED
}

export type SetupCode = Identity & {setupcode: string | null; setupuri: string | null};

// noinspection JSUnusedGlobalSymbols
/**
* @deprecated Use AccessoryEventTypes instead
Expand All @@ -280,6 +289,8 @@ export const enum AccessoryEventTypes {
*/
IDENTIFY = "identify",
LISTENING = "listening",
PAIR_SETUP_STARTED = 'pair-setup-started',
PAIR_SETUP_FINISHED = 'pair-setup-finished',
SERVICE_CONFIGURATION_CHANGE = "service-configurationChange",
/**
* Emitted after a change in the value of one of the provided Service's Characteristics.
Expand All @@ -298,6 +309,9 @@ export declare interface Accessory {
on(event: "service-configurationChange", listener: (change: ServiceConfigurationChange) => void): this;
on(event: "service-characteristic-change", listener: (change: AccessoryCharacteristicChange) => void): this;

on(event: "pair-setup-started", listener: (setupcode: SetupCode, connection: HAPConnection) => void): this;
on(event: "pair-setup-finished", listener: (err: Error | null, clientUsername: string | null, connection: HAPConnection) => void): this;

on(event: "paired", listener: () => void): this;
on(event: "unpaired", listener: () => void): this;

Expand All @@ -310,6 +324,9 @@ export declare interface Accessory {
emit(event: "service-configurationChange", change: ServiceConfigurationChange): boolean;
emit(event: "service-characteristic-change", change: AccessoryCharacteristicChange): boolean;

emit(event: "pair-setup-started", setupcode: SetupCode, connection: HAPConnection): boolean;
emit(event: "pair-setup-finished", err: Error | null, clientUsername: string | null, connection: HAPConnection): boolean;

emit(event: "paired"): boolean;
emit(event: "unpaired"): boolean;

Expand Down Expand Up @@ -855,39 +872,6 @@ export class Accessory extends EventEmitter {
});
}

setupURI(): string {
if (this._setupURI) {
return this._setupURI;
}

const buffer = Buffer.alloc(8);
const setupCode = this._accessoryInfo && parseInt(this._accessoryInfo.pincode.replace(/-/g, ''), 10);

let value_low = setupCode!;
const value_high = this._accessoryInfo && this._accessoryInfo.category >> 1;

value_low |= 1 << 28; // Supports IP;

buffer.writeUInt32BE(value_low, 4);

if (this._accessoryInfo && this._accessoryInfo.category & 1) {
buffer[4] = buffer[4] | 1 << 7;
}

buffer.writeUInt32BE(value_high!, 0);

let encodedPayload = (buffer.readUInt32BE(4) + (buffer.readUInt32BE(0) * Math.pow(2, 32))).toString(36).toUpperCase();

if (encodedPayload.length != 9) {
for (let i = 0; i <= 9 - encodedPayload.length; i++) {
encodedPayload = "0" + encodedPayload;
}
}

this._setupURI = "X-HM://" + encodedPayload + this._setupID;
return this._setupURI;
}

/**
* This method is called right before the accessory is published. It should be used to check for common
* mistakes in Accessory structured, which may lead to HomeKit rejecting the accessory when pairing.
Expand Down Expand Up @@ -1057,8 +1041,9 @@ export class Accessory extends EventEmitter {
* @param allowInsecureRequest - Will allow unencrypted and unauthenticated access to the http server
* @param {string} info.username - The "username" (formatted as a MAC address - like "CC:22:3D:E3:CE:F6") of
* this Accessory. Must be globally unique from all Accessories on your local network.
* @param {string} info.pincode - The 8-digit pincode for clients to use when pairing this Accessory. Must be formatted
* as a string like "031-45-154".
* @param {string|function} info.pincode - The 8-digit pincode for clients to use when pairing this Accessory. Must
* be formatted as a string like "031-45-154". You can also provide a function that
* generates a random setup code and presents it to the user.
* @param {string} info.category - One of the values of the Accessory.Category enum, like Accessory.Category.SWITCH.
* This is a hint to iOS clients about what "type" of Accessory this represents, so
* that for instance an appropriate icon can be drawn for the user while adding a
Expand Down Expand Up @@ -1101,7 +1086,7 @@ export class Accessory extends EventEmitter {
if (info.setupID) {
this._setupID = info.setupID;
} else if (this._accessoryInfo.setupID === undefined || this._accessoryInfo.setupID === "") {
this._setupID = Accessory._generateSetupID();
this._setupID = generateSetupId();
} else {
this._setupID = this._accessoryInfo.setupID;
}
Expand All @@ -1112,7 +1097,7 @@ export class Accessory extends EventEmitter {
this._accessoryInfo.displayName = this.displayName;
this._accessoryInfo.model = this.getService(Service.AccessoryInformation)!.getCharacteristic(Characteristic.Model).value as string;
this._accessoryInfo.category = info.category || Categories.OTHER;
this._accessoryInfo.pincode = info.pincode;
this._accessoryInfo.pincode = info.pincode && typeof info.pincode !== 'function' ? info.pincode : null;
this._accessoryInfo.save();

// create our IdentifierCache so we can provide clients with stable aid/iid's
Expand Down Expand Up @@ -1173,6 +1158,8 @@ export class Accessory extends EventEmitter {
this._server.allowInsecureRequest = !!allowInsecureRequest;
this._server.on(HAPServerEventTypes.LISTENING, this.onListening.bind(this));
this._server.on(HAPServerEventTypes.IDENTIFY, this.identificationRequest.bind(this, false));
this._server.on(HAPServerEventTypes.PAIR_SETUP_STARTED, this._handlePairSetupStarted.bind(this));
this._server.on(HAPServerEventTypes.PAIR_SETUP_FINISHED, this._handlePairSetupFinished.bind(this));
this._server.on(HAPServerEventTypes.PAIR, this.handleInitialPairSetupFinished.bind(this));
this._server.on(HAPServerEventTypes.ADD_PAIRING, this.handleAddPairing.bind(this));
this._server.on(HAPServerEventTypes.REMOVE_PAIRING, this.handleRemovePairing.bind(this));
Expand All @@ -1183,6 +1170,12 @@ export class Accessory extends EventEmitter {
this._server.on(HAPServerEventTypes.CONNECTION_CLOSED, this.handleHAPConnectionClosed.bind(this));
this._server.on(HAPServerEventTypes.REQUEST_RESOURCE, this.handleResource.bind(this));

if (typeof info.pincode === 'function') {
this._server.on(HAPServerEventTypes.GENERATE_SETUP_CODE, info.pincode);
} else if (typeof info.pincode !== 'string' && typeof info.pincode !== 'object') {
this._server.on(HAPServerEventTypes.GENERATE_SETUP_CODE, generateSetupCode);
}

this._server.listen(info.port, parsed.serverAddress);
}

Expand Down Expand Up @@ -1249,6 +1242,23 @@ export class Accessory extends EventEmitter {
this.emit(AccessoryEventTypes.LISTENING, port, hostname);
}

/** Called when starting the pair setup process after a setup code has been generated */
private _handlePairSetupStarted(i: PairIdentity, connection: HAPConnection) {
if (this.listenerCount(AccessoryEventTypes.PAIR_SETUP_STARTED)) {
if (!this._setupID) this._setupID = generateSetupId();
const setupuri = i.setupcode ? generateSetupUri(i.setupcode, this._setupID, this.category) : null;
this.emit(AccessoryEventTypes.PAIR_SETUP_STARTED, {...i, setupuri}, connection);
} else if (!this._accessoryInfo!.pincode) {
// If we're using random setup codes and there's nothing listening for the setup code print it to the console
console.log('[%s] Received pair request from %s', this.displayName, connection.remoteAddress, i.setupcode);
}
}

/** Called when the pair setup process has finished with the error or paired client username */
private _handlePairSetupFinished(err: Nullable<Error>, clientUsername: Nullable<string>, connection: HAPConnection) {
this.emit(AccessoryEventTypes.PAIR_SETUP_FINISHED, err, clientUsername, connection);
}

private handleInitialPairSetupFinished(username: string, publicKey: Buffer, callback: PairCallback): void {
debug("[%s] Paired with client %s", this.displayName, username);

Expand Down Expand Up @@ -1851,19 +1861,6 @@ export class Accessory extends EventEmitter {
});
}

private static _generateSetupID(): string {
const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
const bytes = crypto.randomBytes(4);
let setupID = '';

for (let i = 0; i < 4; i++) {
const index = bytes.readUInt8(i) % 26;
setupID += chars.charAt(index);
}

return setupID;
}

// serialization and deserialization functions, mainly designed for homebridge to create a json copy to store on disk
public static serialize(accessory: Accessory): SerializedAccessory {
const json: SerializedAccessory = {
Expand Down
10 changes: 2 additions & 8 deletions src/lib/Advertiser.ts
Expand Up @@ -7,9 +7,9 @@ import ciao, {
ServiceType
} from "@homebridge/ciao";
import { ServiceOptions } from "@homebridge/ciao/lib/CiaoService";
import crypto from 'crypto';
import { EventEmitter } from "events";
import { AccessoryInfo } from './model/AccessoryInfo';
import { generateSetupHash } from "./util/setupid";

/**
* This enum lists all bitmasks for all known status flags.
Expand Down Expand Up @@ -62,7 +62,7 @@ export class Advertiser extends EventEmitter {
constructor(accessoryInfo: AccessoryInfo, responderOptions?: MDNSServerOptions, serviceOptions?: Partial<ServiceOptions>) {
super();
this.accessoryInfo = accessoryInfo;
this.setupHash = this.computeSetupHash();
this.setupHash = generateSetupHash(this.accessoryInfo.username, this.accessoryInfo.setupID).toString('base64');

this.responder = ciao.getResponder({
ignoreUnicastResponseFlag: true, // used for debugging
Expand Down Expand Up @@ -120,12 +120,6 @@ export class Advertiser extends EventEmitter {
};
}

private computeSetupHash(): string {
const hash = crypto.createHash('sha512');
hash.update(this.accessoryInfo.setupID + this.accessoryInfo.username.toUpperCase());
return hash.digest().slice(0, 4).toString('base64');
}

public static ff(...flags: PairingFeatureFlag[]): number {
let value = 0;
flags.forEach(flag => value |= flag);
Expand Down

0 comments on commit bf825fc

Please sign in to comment.