@aptre/bldr-saucer 0.2.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CMakeLists.txt +0 -1
- package/package.json +6 -6
- package/src/main.cpp +2 -2
- package/src/pipe_client.cpp +14 -6
- package/src/scheme_forwarder.cpp +27 -21
package/CMakeLists.txt
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aptre/bldr-saucer",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "Native webview bridge for Bldr using Saucer",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"repository": {
|
|
@@ -33,11 +33,11 @@
|
|
|
33
33
|
"release:publish": "git push && git push --tags"
|
|
34
34
|
},
|
|
35
35
|
"optionalDependencies": {
|
|
36
|
-
"@aptre/bldr-saucer-darwin-arm64": "0.2.
|
|
37
|
-
"@aptre/bldr-saucer-darwin-x64": "0.2.
|
|
38
|
-
"@aptre/bldr-saucer-linux-x64": "0.2.
|
|
39
|
-
"@aptre/bldr-saucer-linux-arm64": "0.2.
|
|
40
|
-
"@aptre/bldr-saucer-win32-x64": "0.2.
|
|
36
|
+
"@aptre/bldr-saucer-darwin-arm64": "0.2.3",
|
|
37
|
+
"@aptre/bldr-saucer-darwin-x64": "0.2.3",
|
|
38
|
+
"@aptre/bldr-saucer-linux-x64": "0.2.3",
|
|
39
|
+
"@aptre/bldr-saucer-linux-arm64": "0.2.3",
|
|
40
|
+
"@aptre/bldr-saucer-win32-x64": "0.2.3"
|
|
41
41
|
},
|
|
42
42
|
"files": [
|
|
43
43
|
"index.js",
|
package/src/main.cpp
CHANGED
|
@@ -21,8 +21,8 @@ coco::stray start(saucer::application* app) {
|
|
|
21
21
|
const char* init_b64 = std::getenv("BLDR_SAUCER_INIT");
|
|
22
22
|
if (init_b64) {
|
|
23
23
|
auto data = bldr::proto::Base64Decode(init_b64);
|
|
24
|
-
if (!data.empty()) {
|
|
25
|
-
|
|
24
|
+
if (!data.empty() && !bldr::proto::DecodeSaucerInit(data.data(), data.size(), saucer_init)) {
|
|
25
|
+
std::cerr << "Failed to decode BLDR_SAUCER_INIT" << std::endl;
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
|
package/src/pipe_client.cpp
CHANGED
|
@@ -40,7 +40,7 @@ bool PipeClient::connect(const std::string& pipe_path) {
|
|
|
40
40
|
return false;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
// Set pipe
|
|
43
|
+
// Set pipe to byte read mode.
|
|
44
44
|
DWORD mode = PIPE_READMODE_BYTE;
|
|
45
45
|
if (!SetNamedPipeHandleState(handle_, &mode, nullptr, nullptr)) {
|
|
46
46
|
std::cerr << "Failed to set pipe mode: " << GetLastError() << std::endl;
|
|
@@ -193,12 +193,20 @@ bool PipeClient::write(const uint8_t* data, size_t length) {
|
|
|
193
193
|
}
|
|
194
194
|
|
|
195
195
|
#ifdef _WIN32
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
196
|
+
size_t total_written = 0;
|
|
197
|
+
while (total_written < length) {
|
|
198
|
+
DWORD bytes_written = 0;
|
|
199
|
+
if (!WriteFile(handle_, data + total_written, (DWORD)(length - total_written), &bytes_written, nullptr)) {
|
|
200
|
+
connected_ = false;
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
if (bytes_written == 0) {
|
|
204
|
+
connected_ = false;
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
total_written += bytes_written;
|
|
200
208
|
}
|
|
201
|
-
return
|
|
209
|
+
return true;
|
|
202
210
|
#else
|
|
203
211
|
size_t total_written = 0;
|
|
204
212
|
while (total_written < length) {
|
package/src/scheme_forwarder.cpp
CHANGED
|
@@ -1,18 +1,33 @@
|
|
|
1
1
|
#include "scheme_forwarder.h"
|
|
2
2
|
|
|
3
|
+
#include <algorithm>
|
|
4
|
+
#include <cctype>
|
|
3
5
|
#include <cstring>
|
|
4
6
|
#include <iostream>
|
|
5
7
|
|
|
6
8
|
namespace bldr {
|
|
7
9
|
|
|
10
|
+
// toLower returns a lowercase copy of the string.
|
|
11
|
+
static std::string toLower(const std::string& s) {
|
|
12
|
+
std::string out = s;
|
|
13
|
+
std::transform(out.begin(), out.end(), out.begin(),
|
|
14
|
+
[](unsigned char c) { return std::tolower(c); });
|
|
15
|
+
return out;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// sendError sends an error response to the saucer writer.
|
|
19
|
+
static void sendError(saucer::scheme::stream_writer& writer, int status) {
|
|
20
|
+
writer.start({.mime = "text/plain", .status = status});
|
|
21
|
+
writer.finish();
|
|
22
|
+
}
|
|
23
|
+
|
|
8
24
|
void SchemeForwarder::forward(const saucer::scheme::request& req,
|
|
9
25
|
saucer::scheme::stream_writer& writer) {
|
|
10
26
|
// Open a new yamux stream.
|
|
11
27
|
auto [stream, err] = session_->OpenStream();
|
|
12
28
|
if (err != yamux::Error::OK || !stream) {
|
|
13
29
|
std::cerr << "[forwarder] failed to open yamux stream" << std::endl;
|
|
14
|
-
writer
|
|
15
|
-
writer.finish();
|
|
30
|
+
sendError(writer, 502);
|
|
16
31
|
return;
|
|
17
32
|
}
|
|
18
33
|
|
|
@@ -35,8 +50,7 @@ void SchemeForwarder::forward(const saucer::scheme::request& req,
|
|
|
35
50
|
if (!writeFrame(stream.get(), reqInfoMsg)) {
|
|
36
51
|
std::cerr << "[forwarder] failed to write request info" << std::endl;
|
|
37
52
|
stream->Close();
|
|
38
|
-
writer
|
|
39
|
-
writer.finish();
|
|
53
|
+
sendError(writer, 502);
|
|
40
54
|
return;
|
|
41
55
|
}
|
|
42
56
|
|
|
@@ -53,8 +67,7 @@ void SchemeForwarder::forward(const saucer::scheme::request& req,
|
|
|
53
67
|
if (!writeFrame(stream.get(), reqDataMsg)) {
|
|
54
68
|
std::cerr << "[forwarder] failed to write request body" << std::endl;
|
|
55
69
|
stream->Close();
|
|
56
|
-
writer
|
|
57
|
-
writer.finish();
|
|
70
|
+
sendError(writer, 502);
|
|
58
71
|
return;
|
|
59
72
|
}
|
|
60
73
|
}
|
|
@@ -67,7 +80,7 @@ void SchemeForwarder::forward(const saucer::scheme::request& req,
|
|
|
67
80
|
std::vector<uint8_t> frame;
|
|
68
81
|
if (!readFrame(stream.get(), frame)) {
|
|
69
82
|
if (!started) {
|
|
70
|
-
writer
|
|
83
|
+
sendError(writer, 502);
|
|
71
84
|
}
|
|
72
85
|
break;
|
|
73
86
|
}
|
|
@@ -76,7 +89,7 @@ void SchemeForwarder::forward(const saucer::scheme::request& req,
|
|
|
76
89
|
if (!proto::DecodeFetchResponse(frame.data(), frame.size(), resp)) {
|
|
77
90
|
std::cerr << "[forwarder] failed to decode response" << std::endl;
|
|
78
91
|
if (!started) {
|
|
79
|
-
writer
|
|
92
|
+
sendError(writer, 502);
|
|
80
93
|
}
|
|
81
94
|
break;
|
|
82
95
|
}
|
|
@@ -85,20 +98,13 @@ void SchemeForwarder::forward(const saucer::scheme::request& req,
|
|
|
85
98
|
if (resp.has_info && !started) {
|
|
86
99
|
started = true;
|
|
87
100
|
|
|
88
|
-
//
|
|
101
|
+
// Extract Content-Type header (case-insensitive).
|
|
89
102
|
std::string mime = "application/octet-stream";
|
|
90
|
-
auto it = resp.info.headers.find("Content-Type");
|
|
91
|
-
if (it == resp.info.headers.end()) {
|
|
92
|
-
it = resp.info.headers.find("content-type");
|
|
93
|
-
}
|
|
94
|
-
if (it != resp.info.headers.end()) {
|
|
95
|
-
mime = it->second;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// Build response headers for saucer (excluding Content-Type which goes in mime).
|
|
99
103
|
std::map<std::string, std::string> hdrs;
|
|
100
104
|
for (const auto& [key, val] : resp.info.headers) {
|
|
101
|
-
if (key
|
|
105
|
+
if (toLower(key) == "content-type") {
|
|
106
|
+
mime = val;
|
|
107
|
+
} else {
|
|
102
108
|
hdrs[key] = val;
|
|
103
109
|
}
|
|
104
110
|
}
|
|
@@ -135,7 +141,7 @@ bool SchemeForwarder::writeFrame(yamux::Stream* stream, const std::vector<uint8_
|
|
|
135
141
|
// Write LittleEndian uint32 length prefix.
|
|
136
142
|
uint8_t lenBuf[4];
|
|
137
143
|
uint32_t msgLen = static_cast<uint32_t>(data.size());
|
|
138
|
-
std::memcpy(lenBuf, &msgLen, 4); // LE on LE platforms
|
|
144
|
+
std::memcpy(lenBuf, &msgLen, 4); // LE on LE platforms (x86_64, ARM64)
|
|
139
145
|
|
|
140
146
|
auto err = stream->Write(lenBuf, 4);
|
|
141
147
|
if (err != yamux::Error::OK) return false;
|
|
@@ -155,7 +161,7 @@ bool SchemeForwarder::readFrame(yamux::Stream* stream, std::vector<uint8_t>& out
|
|
|
155
161
|
}
|
|
156
162
|
|
|
157
163
|
uint32_t msgLen;
|
|
158
|
-
std::memcpy(&msgLen, lenBuf, 4); // LE on LE platforms
|
|
164
|
+
std::memcpy(&msgLen, lenBuf, 4); // LE on LE platforms (x86_64, ARM64)
|
|
159
165
|
|
|
160
166
|
if (msgLen > kMaxFrameSize) return false;
|
|
161
167
|
|