Skip to content

Commit

Permalink
Refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
tsutsu3 committed Nov 24, 2024
1 parent 64dc49f commit ae43257
Show file tree
Hide file tree
Showing 10 changed files with 205 additions and 162 deletions.
26 changes: 23 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,31 @@ yarn add unbound-control-ts

Here's a basic example to demonstrate how to use the library:

Use domain socket:
```ts
import { UnboundControlClient } from 'unbound-control-ts';
import { UnixUnboundClient } from 'unbound-control-ts';

const client = new UnboundControlClient('/path/to/unbound-control.sock');
const client = new UnixUnboundClient('/path/to/unbound-control.sock');

(async () => {
try {
const response = await client.status();
console.log(response);
} catch (error) {
if (error instanceof UnboundError) {
console.error(error.message);
} else {
console.error(error);
}
}
})();
```

Use tcp socket:
```ts
import { TcpUnboundClient } from 'unbound-control-ts';

const client = new TcpUnboundClient('localhost', 8953);

(async () => {
try {
Expand Down Expand Up @@ -142,7 +163,6 @@ Before you begin, ensure you have the following tools installed on your system:
- **Node.js**: Version 16 or later. [Download Node.js](https://nodejs.org/)
- **npm**: Comes with Node.js, or install it separately if needed.
- **Unbound**: Ensure that `unbound-control` is installed and properly configured. Follow the [Unbound installation guide](https://nlnetlabs.nl/documentation/unbound/) for details.
- **TypeScript**: (Optional) For contributing to or extending the library, TypeScript must be installed globally or as a dev dependency.

### Develop Setup

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"test": "jest --detectOpenHandles tests/control.test.ts",
"test:it": "jest --detectOpenHandles tests/control.it.test.ts",
"snapshot": "jest --detectOpenHandles tests/control.snapshot.test.ts",
"snapshot:update": "jest --detectOpenHandles --updateSnapshot tests/control.snapshot.test.ts",
"sample:esm": "node examples/index.mjs",
"sample:cjs": "node examples/index.cjs",
"sample": "npm run test:esm:node && npm run test:cjs:node"
Expand Down
130 changes: 24 additions & 106 deletions src/client.ts
Original file line number Diff line number Diff line change
@@ -1,116 +1,21 @@
import { UnboundControl } from "./control";
import { ParseError } from "./error";
import { Response, TlsConfig, NestedRecord, ValidOption } from "./types";

/**
* A list of valid configuration options for the `set_option` command.
*/
export type ValidOption =
| "statistics-interval"
| "statistics-cumulative"
| "do-not-query-localhost"
| "harden-short-bufsize"
| "harden-large-queries"
| "harden-glue"
| "harden-dnssec-stripped"
| "harden-below-nxdomain"
| "harden-referral-path"
| "prefetch"
| "prefetch-key"
| "log-queries"
| "hide-identity"
| "hide-version"
| "identity"
| "version"
| "val-log-level"
| "val-log-squelch"
| "ignore-cd-flag"
| "add-holddown"
| "del-holddown"
| "keep-missing"
| "tcp-upstream"
| "ssl-upstream"
| "max-udp-size"
| "ratelimit"
| "ip-ratelimit"
| "cache-max-ttl"
| "cache-min-ttl"
| "cache-max-negative-ttl";

export interface Response {
raw: string;
json: any; // eslint-disable-line @typescript-eslint/no-explicit-any
}

// export interface StatusResponse {
// version: string;
// verbosity: number;
// threads: number;
// modules: string[];
// uptime: number;
// options: string[];
// pid: number;
// status: string;
// }

// export interface StasResponse {
// total: {
// num: {
// queries: number;
// queries_ip_ratelimited: number;
// queries_cookie_valid: number;
// queries_cookie_client: number;
// queries_cookie_invalid: number;
// cachehits: number;
// cachemiss: number;
// prefetch: number;
// queries_timed_out: number;
// expired: number;
// recursivereplies: number;
// };
// query: {
// queue_time_us: {
// max: number;
// };
// };
// requestlist: {
// avg: number;
// max: number;
// overwritten: number;
// exceeded: number;
// current: {
// all: number;
// user: number;
// };
// };
// recursion: {
// time: {
// avg: number;
// median: number;
// };
// };
// tcpusage: number;
// };
// time: {
// now: number;
// up: number;
// elapsed: number;
// };
// }

export interface NestedRecord {
[key: string]: string | number | string[] | NestedRecord;
}

export class UnboundControlClient {
abstract class UnboundControlClient {
private control: UnboundControl;

constructor(
unixSocketName: string | null = null,
// host: string = "127.0.0.1",
// port: number = 8953,
// tlsConfig?: TLSConfig,
unixSocketName: string | null,
host?: string,
port?: number,
tlsConfig?: TlsConfig | null,
) {
this.control = new UnboundControl(unixSocketName);
if (unixSocketName) {
this.control = new UnboundControl(unixSocketName);
} else {
this.control = new UnboundControl(null, host, port, tlsConfig);
}
}

/**
Expand Down Expand Up @@ -951,3 +856,16 @@ export class UnboundControlClient {
};
}
}

export class UnixUnboundClient extends UnboundControlClient {
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
constructor(unixSocketName: string) {
super(unixSocketName);
}
}

export class TcpUnboundClient extends UnboundControlClient {
constructor(host: string, port: number, tlsConfig?: TlsConfig) {
super(null, host, port, tlsConfig);
}
}
69 changes: 30 additions & 39 deletions src/control.ts
Original file line number Diff line number Diff line change
@@ -1,44 +1,29 @@
import net from "net";
import tls from "tls";
import fs from "fs";
import { ConnectionError, CommandError } from "./error";
// import tls from "tls";

/**
* Configuration for the TLS connection.
*/
// export interface TLSConfig {
// /** Certificate file. */
// cert: string;

// /** Key file. */
// key: string;

// /** CA certificate file. */
// ca?: string;

// /** Reject unauthorized connections. If set to false, the server certificate is not verified. */
// rejectUnauthorized: boolean;
// }
import { TlsConfig } from "./types";

/**
* A class to interact with an Unbound control interface via TCP or Unix socket.
* Provides methods to establish connections and send commands to the Unbound DNS resolver.
*/
export class UnboundControl {
/** The path to the Unix domain socket (if applicable). */
private readonly unixSocketName: string | null;

/** The host address for TCP connections. */
// private readonly host: string;
private readonly host: string;

/** The port number for TCP connections. */
// private readonly port: number;
private readonly port: number;

/** The path to the Unix domain socket (if applicable). */
private readonly unixSocketName: string | null;
/** Optional TLS configuration for secure connections. */
private readonly tlsConfig: TlsConfig | null = null;

/** The underlying network socket for communication. */
private socket: net.Socket | null = null;

/** Optional TLS configuration for secure connections. */
// private readonly tlsConfig: TLSConfig | null = null;

/**
* Creates a new instance of the UnboundControl class.
*
Expand All @@ -49,14 +34,14 @@ export class UnboundControl {
*/
constructor(
unixSocketName: string | null = null,
// host: string = "127.0.0.1",
// port: number = 8953,
// tlsConfig?: TLSConfig,
host: string = "localhost",
port: number = 8953,
tlsConfig: TlsConfig | null = null,
) {
this.unixSocketName = unixSocketName;
// this.host = host;
// this.port = port;
// this.tlsConfig = tlsConfig || null;
this.host = host;
this.port = port;
this.tlsConfig = tlsConfig;
}

/**
Expand All @@ -79,15 +64,21 @@ export class UnboundControl {
if (this.unixSocketName !== null) {
socket = net.createConnection(this.unixSocketName);
} else {
throw new Error("Not implemented");
if (this.tlsConfig) {
socket = tls.connect({
host: this.host,
port: this.port,
rejectUnauthorized: this.tlsConfig.ca ? true : false,
cert: fs.readFileSync(this.tlsConfig.cert),
key: fs.readFileSync(this.tlsConfig.key),
ca: this.tlsConfig.ca
? fs.readFileSync(this.tlsConfig.ca)
: undefined,
});
} else {
socket = net.createConnection(this.port, this.host);
}
}
// else {
// socket = tls.createConnection({
// host: this.host,
// port: this.port,
// ...this.tlsConfig,
// });
// }

socket.once("connect", () => {
this.socket = socket;
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export { UnboundControl } from "./control";
export { UnboundControlClient } from "./client";
export { UnixUnboundClient, TcpUnboundClient } from "./client";
export {
UnboundError,
ConnectionError,
Expand Down
Loading

0 comments on commit ae43257

Please sign in to comment.