<commit_before>// This implements the interface from the 'bonjour' npm package using the
// avahi-browse command. Not all features are implemented.

import * as avahi from 'avahi-dbus';
import * as bonjour from 'bonjour';
import * as bonjour2 from '../bonjour';
import * as dbus from 'dbus-native';
import * as events from 'events';
import * as vscode from 'vscode';

let bus;
let avahiDaemon;

export function isPresent(): boolean {
    if (bus && avahiDaemon) {
        return true;
    }
    try {
        bus = dbus.systemBus();
        avahiDaemon = new avahi.Daemon(bus);
        return true;
    }
    catch (err) {
        return false;
    }
}

export function getInstance(): bonjour2.Bonjour {
    if (!isPresent()) {
        throw 'Not present';
    }
    return new Avahi();
}

class Avahi implements bonjour2.Bonjour {
    private destroyOps = new Array<()=>void>();

    // interface method implementation
    public find(options: bonjour.BrowserOptions, onUp?: (service: bonjour.Service) => void): bonjour.Browser {
        const browser = new AvahiBrowser(this, options);
        if (onUp) {
            browser.on('up', onUp);
        }
        return browser;
    }

    // interface method implementation
    public destroy(): void {
        this.destroyOps.forEach(op => op());
        this.destroyOps.length = 0;
    }

    /**
     * Adds an operation to be performed when destroy() is called.
     * @param op operation to add
     * @return the op argument
     */
    pushDestroyOp(op: ()=>void): ()=>void {
        this.destroyOps.push(op);
        return op;
    }

    /**
     * Removes an operation that was added with pushDestroyOp()
     * @param op the operation to remove
     */
    popDestroyOp(op: ()=>void): void {
        let i = this.destroyOps.findIndex(v => v == op);
        if (i >= 0) {
            this.destroyOps.splice(i, 1);
        }
    }
}

class AvahiBrowser extends events.EventEmitter implements bonjour.Browser {
    private browser: any;
    private destroyOp: ()=>void;
    readonly services: bonjour.Service[] = new Array<bonjour.Service>();

    constructor(private avahi: Avahi, private options: bonjour.BrowserOptions) {
        super();
    }

    start(): void {
        if (this.destroyOp) {
            throw 'Already started';
        }
        this.destroyOp = this.avahi.pushDestroyOp(() => this.stop());
        const type = `_${this.options.type}._${this.options.protocol || 'tcp'}`;
        // FIXME: 'local' is not necessarily the default domain, but dbus-native
        // can't encode null
        avahiDaemon.ServiceBrowserNew(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, type, 'local', 0,
            (err, browser) => {
                if (!this.destroyOp) {
                    // service was stopped before callback
                    return;
                }<commit_msg>empty string seems to work for default domain<commit_after>// This implements the interface from the 'bonjour' npm package using the
// avahi-browse command. Not all features are implemented.

import * as avahi from 'avahi-dbus';
import * as bonjour from 'bonjour';
import * as bonjour2 from '../bonjour';
import * as dbus from 'dbus-native';
import * as events from 'events';
import * as vscode from 'vscode';

let bus;
let avahiDaemon;

export function isPresent(): boolean {
    if (bus && avahiDaemon) {
        return true;
    }
    try {
        bus = dbus.systemBus();
        avahiDaemon = new avahi.Daemon(bus);
        return true;
    }
    catch (err) {
        return false;
    }
}

export function getInstance(): bonjour2.Bonjour {
    if (!isPresent()) {
        throw 'Not present';
    }
    return new Avahi();
}

class Avahi implements bonjour2.Bonjour {
    private destroyOps = new Array<()=>void>();

    // interface method implementation
    public find(options: bonjour.BrowserOptions, onUp?: (service: bonjour.Service) => void): bonjour.Browser {
        const browser = new AvahiBrowser(this, options);
        if (onUp) {
            browser.on('up', onUp);
        }
        return browser;
    }

    // interface method implementation
    public destroy(): void {
        this.destroyOps.forEach(op => op());
        this.destroyOps.length = 0;
    }

    /**
     * Adds an operation to be performed when destroy() is called.
     * @param op operation to add
     * @return the op argument
     */
    pushDestroyOp(op: ()=>void): ()=>void {
        this.destroyOps.push(op);
        return op;
    }

    /**
     * Removes an operation that was added with pushDestroyOp()
     * @param op the operation to remove
     */
    popDestroyOp(op: ()=>void): void {
        let i = this.destroyOps.findIndex(v => v == op);
        if (i >= 0) {
            this.destroyOps.splice(i, 1);
        }
    }
}

class AvahiBrowser extends events.EventEmitter implements bonjour.Browser {
    private browser: any;
    private destroyOp: ()=>void;
    readonly services: bonjour.Service[] = new Array<bonjour.Service>();

    constructor(private avahi: Avahi, private options: bonjour.BrowserOptions) {
        super();
    }

    start(): void {
        if (this.destroyOp) {
            throw 'Already started';
        }
        this.destroyOp = this.avahi.pushDestroyOp(() => this.stop());
        const type = `_${this.options.type}._${this.options.protocol || 'tcp'}`;
        avahiDaemon.ServiceBrowserNew(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, type, '', 0,
            (err, browser) => {
                if (!this.destroyOp) {
                    // service was stopped before callback
                    return;
                }
{'fraction_non_alphanumeric': 0.12306046013911183, 'fraction_numerical': 0.0024968789013732834, 'mean_word_length': 2.310507674144038, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5355336', 'n_tokens_mistral': 1682, 'n_tokens_neox': 1618, 'n_words': 481}