Documentation ¶
Index ¶
- Constants
- func NewEncryptableDialer(...) (...)
- func NewRandomPairingID() []byte
- func NewRandomPin() string
- func WithIdentify(cb func()) option
- func WithLogger(logger log.Logger) option
- type AccessoryDevice
- type AccessorySRPSession
- type Controller
- type Database
- type Device
- type HTTPServer
- type VerifyClientController
Examples ¶
Constants ¶
const ContentType = "application/pairing+tlv8"
Variables ¶
This section is empty.
Functions ¶
func NewEncryptableDialer ¶
func NewEncryptableDialer(dial func(ctx context.Context, network string, address string) (net.Conn, error)) (dialContext func(ctx context.Context, network string, address string) (net.Conn, error), encrypt func(sharedKey [32]byte) error)
NewEncryptableDialer should be used for homekit client, to wrap a (&net.Dialer{...}).DialContext (see Example).
Example ¶
package main import ( "net" "net/http" "time" "code.pfad.fr/gohmekit/pairing" ) func main() { dial, encrypt := pairing.NewEncryptableDialer((&net.Dialer{ Timeout: 5 * time.Second, KeepAlive: 5 * time.Second, }).DialContext) httpClient := http.Client{ Transport: &http.Transport{ Proxy: http.ProxyFromEnvironment, DialContext: dial, ForceAttemptHTTP2: false, MaxIdleConns: 1, IdleConnTimeout: 5 * time.Second, TLSHandshakeTimeout: 5 * time.Second, ExpectContinueTimeout: 5 * time.Second, }, } // do whatever you need with the httpClient // call encrypt(sharedKey) to encrypt further communications. _ = encrypt _ = httpClient }
Output:
func NewRandomPairingID ¶
func NewRandomPairingID() []byte
NewRandomPin generates a random 48-bits pairingID.
func WithIdentify ¶
func WithIdentify(cb func()) option
WithIdentify allows to specify a function to call when the device should physically identify itself (before pairing).
func WithLogger ¶
WithLogger adds structured logging to the pairing server.
Types ¶
type AccessoryDevice ¶
type AccessoryDevice interface { Device SRPSession() (sess AccessorySRPSession, salt []byte, err error) }
AccessoryDevice interface must be implemented by the accessory to support pairing.
func NewDeviceWithPin ¶
func NewDeviceWithPin(deviceID []byte, pin string, ed25519PrivateKey []byte) (AccessoryDevice, error)
NewDeviceWithPin creates a new AccessoryDevice with the given id, pin and private key.
type AccessorySRPSession ¶
type Controller ¶
Controller is used to store the devices in the Database.
type Database ¶
type Database interface { IsPaired() bool GetLongTermPublicKey([]byte) ([]byte, error) AddLongTermPublicKey(Controller) error RemoveLongTermPublicKey(id []byte) error ListLongTermPublicKey() ([]Controller, error) }
Database interface for the accessory to store its state.
type Device ¶
type Device interface { PairingID() []byte Ed25519Sign([]byte) ([]byte, error) OwnLongTermPublicKey() []byte }
Device interface must be implemented by the controller to support pairing.
type HTTPServer ¶
type HTTPServer struct { Identify func() // when called, the device must identify itself (by sound, light...) Logger log.Logger // github.com/go-kit/log.NewNopLogger() if you don't want any log Device AccessoryDevice Database Database // contains filtered or unexported fields }
HTTPServer must be created with NewServer and can be adjusted afterwards.
func NewServer ¶
func NewServer(server *http.Server, device AccessoryDevice, db Database, options ...option) *HTTPServer
NewServer creates a new pairing server. Once the accessory is paired, it will forward all decrypted communications to the given server.
func (*HTTPServer) ListenAndServe ¶
func (srv *HTTPServer) ListenAndServe() error
ListenAndServe listens on the TCP network address of the underlying http.Server (server.Addr) and then calls Serve to handle requests on incoming connections.
If the address is blank, ":http" is used.
ListenAndServe always returns a non-nil error. After Shutdown or Close, the returned error is ErrServerClosed.
func (*HTTPServer) Listener ¶
func (srv *HTTPServer) Listener() (net.Listener, error)
Listener returns a new listener on the TCP network address of the underlying http.Server (server.Addr).
If the address is blank, ":http" is used.
type VerifyClientController ¶
type VerifyClientController struct {
// contains filtered or unexported fields
}
VerifyClientController implements the client logic for the pairing-verify step.
func NewVerifyClientController ¶
func NewVerifyClientController(client Device, database Database) (*VerifyClientController, error)
NewVerifyClientController implements the client logic for the pairing-verify step.
func (VerifyClientController) FinishRequest ¶
func (c VerifyClientController) FinishRequest(r io.Reader) (response []byte, sharedSecret []byte, err error)
FinishRequest checks the accessory initial response and generate the finish request.
func (VerifyClientController) FinishResponse ¶
func (c VerifyClientController) FinishResponse(r io.Reader) error
FinishResponse checks the response of the accessory. From now on, the connection must be encrypted using the sharedSecret computed in the FinishRequest step.
func (VerifyClientController) StartRequest ¶
func (c VerifyClientController) StartRequest() []byte
StartRequest is the initial pairing-verify request.