Skip to content

Commit a1cdb22

Browse files
committed
Improves estimate of max recv data
1 parent 5545f0a commit a1cdb22

File tree

1 file changed

+51
-43
lines changed

1 file changed

+51
-43
lines changed

src/offscreen/handlers/notary_prove.ts

Lines changed: 51 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import {
1212
Presentation as TPresentation,
1313
Commit,
1414
NotaryServer,
15-
Transcript,
1615
mapStringToRange,
1716
subtractRanges,
1817
} from 'tlsn-js';
@@ -33,18 +32,24 @@ export const TLSNProveOffscreenHandler = new SimpleOffscreenHandler<TLSNProveOff
3332
async (request) => {
3433
const serverURL = getSteamRequestURL(request.notary_request, request.access_token);
3534

36-
// Getting max sent bytes as close as possible to the real req size is crucial for performance
37-
const maxSentData = calculateRequestSize(serverURL,'GET', {
35+
const maxSentData = calculateRequestSize(serverURL, 'GET', {
3836
'Connection': 'close',
3937
'Host': 'api.steampowered.com',
4038
'Accept-Encoding': 'gzip',
4139
});
4240

41+
const maxRecvData = await calculateResponseSize(serverURL, 'GET', {
42+
'Connection': 'close',
43+
'Host': 'api.steampowered.com',
44+
'Accept-Encoding': 'gzip',
45+
});
46+
47+
console.log(maxSentData, maxRecvData);
4348
const notary = NotaryServer.from(environment.notary.tlsn);
4449

4550
const prover = (await new Prover({
4651
serverDns: 'api.steampowered.com',
47-
maxRecvData: 12000,
52+
maxRecvData,
4853
maxSentData,
4954
})) as TProver;
5055

@@ -61,12 +66,6 @@ export const TLSNProveOffscreenHandler = new SimpleOffscreenHandler<TLSNProveOff
6166
const transcript = await prover.transcript();
6267
const { sent, recv } = transcript;
6368

64-
const {
65-
info: recvInfo,
66-
headers: recvHeaders,
67-
body: recvBody,
68-
} = parseHttpMessage(Buffer.from(recv), 'response');
69-
7069
const commit: Commit = {
7170
sent: subtractRanges(
7271
{ start: 0, end: sent.length },
@@ -98,38 +97,6 @@ export const TLSNProveOffscreenHandler = new SimpleOffscreenHandler<TLSNProveOff
9897
}
9998
);
10099

101-
function parseHttpMessage(buffer: Buffer, type: 'request' | 'response') {
102-
const parser = new HTTPParser(
103-
type === 'request' ? HTTPParser.REQUEST : HTTPParser.RESPONSE,
104-
);
105-
const body: Buffer[] = [];
106-
let complete = false;
107-
let headers: string[] = [];
108-
109-
parser.onBody = (t) => {
110-
body.push(t);
111-
};
112-
113-
parser.onHeadersComplete = (res) => {
114-
headers = res.headers;
115-
};
116-
117-
parser.onMessageComplete = () => {
118-
complete = true;
119-
};
120-
121-
parser.execute(buffer);
122-
parser.finish();
123-
124-
if (!complete) throw new Error(`Could not parse ${type.toUpperCase()}`);
125-
126-
return {
127-
info: buffer.toString('utf-8').split('\r\n')[0] + '\r\n',
128-
headers,
129-
body,
130-
};
131-
}
132-
133100
/**
134101
* Estimates the total request byte size over the wire if sent over HTTP 1.1
135102
*
@@ -142,7 +109,7 @@ function parseHttpMessage(buffer: Buffer, type: 'request' | 'response') {
142109
* @param headers HTTP request headers
143110
* @param body Optional request body
144111
*/
145-
export function calculateRequestSize(url: string, method: 'GET'|'POST', headers: Record<string, string>, body?: string): number {
112+
function calculateRequestSize(url: string, method: 'GET'|'POST', headers: Record<string, string>, body?: string): number {
146113
const requestLineSize = new TextEncoder().encode(
147114
`${method} ${url} HTTP/1.1\r\n`,
148115
).length;
@@ -158,4 +125,45 @@ export function calculateRequestSize(url: string, method: 'GET'|'POST', headers:
158125
: 0;
159126

160127
return requestLineSize + headersSize + 2 + bodySize; // +2 for CRLF after headers
128+
}
129+
130+
/**
131+
* Calculates the exact response byte size for the HTTP request by making the request itself and counting the response
132+
*
133+
* @param url Full request uRL including protocol, domain, path
134+
* @param method HTTP method (ie. "GET")
135+
* @param headers HTTP request headers
136+
* @param body Optional request body
137+
*/
138+
async function calculateResponseSize(url: string, method: 'GET'|'POST', headers: Record<string, string>, body?: string): Promise<number> {
139+
const opts: RequestInit = {method, headers};
140+
if (body) {
141+
opts.body = body;
142+
}
143+
const response = await fetch(url, opts);
144+
145+
const statusLine = `HTTP/1.1 ${response.status} ${response.statusText}`;
146+
let headersSize = statusLine.length + 2; // +2 for CRLF (\r\n)
147+
148+
response.headers.forEach((value, name) => {
149+
console.log(name, value);
150+
headersSize += name.length + value.length + 4; // for ": " and "\r\n"
151+
});
152+
153+
// Not included in fetch headers, but is in the network response
154+
headersSize += 'Connection: close'.length + 2;
155+
headersSize += 'X-N: S'.length + 2;
156+
157+
// Add the final CRLF that separates the headers from the body.
158+
headersSize += 2;
159+
160+
const contentLength = response.headers.get('content-length');
161+
162+
if (!contentLength) {
163+
throw new Error('no content length in response headers')
164+
}
165+
166+
const bodySize = parseInt(contentLength, 10);
167+
168+
return headersSize + bodySize;
161169
}

0 commit comments

Comments
 (0)