Skip to content

Commit 151ac08

Browse files
committed
fix(websocket): correct message length handling in WebSocket callbacks (fixes #9)
- Remove +1 from initial messageLength calculation to use actual content length - Add +1 only when pushing length to script callbacks chore(deps): update dependencies to latest versions - Update IXWebSocket to v11.4.6 - Update yyjson to v0.11.1 - Update zlib to v1.3.1 docs: update documentation for message length handling - Add clarification about null terminator in message length parameter
1 parent 5ce56c5 commit 151ac08

50 files changed

Lines changed: 3401 additions & 3101 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
name: build
22

33
on:
4+
workflow_dispatch:
45
push:
6+
branches:
7+
- "main"
58
paths:
6-
- pushbuild.txt
9+
- "src/**"
10+
- "third_party/**"
711
pull_request:
812
paths:
9-
- pushbuild.txt
13+
- "src/**"
14+
- "third_party/**"
1015

1116
permissions:
1217
contents: write
@@ -37,7 +42,7 @@ jobs:
3742
run: |
3843
sudo dpkg --add-architecture i386
3944
sudo apt-get update
40-
sudo apt-get install -y clang g++-multilib zlib1g-dev libssl-dev zlib1g-dev:i386 libssl-dev:i386
45+
sudo apt-get install -y clang g++-multilib libssl-dev libssl-dev:i386
4146
echo "CC=clang" >> $GITHUB_ENV
4247
echo "CXX=clang++" >> $GITHUB_ENV
4348

AMBuilder

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,24 +25,25 @@ for cxx in builder.targets:
2525
os.path.join(builder.sourcePath, 'src'),
2626
os.path.join(builder.sourcePath, 'third_party', 'ixwebsocket'),
2727
os.path.join(builder.sourcePath, 'third_party', 'yyjson'),
28+
os.path.join(builder.sourcePath, 'third_party', 'zlib'),
29+
]
30+
31+
binary.compiler.postlink += [
32+
ixwebsocket[arch].binary,
33+
libyyjson[arch].binary,
34+
libz[arch].binary,
2835
]
2936

3037
if binary.compiler.target.platform == 'linux':
3138
binary.compiler.postlink += [
32-
'-lz',
3339
'-lssl',
34-
ixwebsocket[arch].binary,
35-
libyyjson[arch].binary,
3640
]
3741
elif binary.compiler.target.platform == 'windows':
3842
binary.compiler.postlink += [
3943
'ws2_32.lib',
4044
'crypt32.lib',
41-
ixwebsocket[arch].binary,
42-
libyyjson[arch].binary,
43-
libz[arch].binary,
4445
os.path.join(builder.sourcePath, 'third_party', 'openssl', 'lib', 'libssl_static_{}.lib'.format(arch)),
4546
os.path.join(builder.sourcePath, 'third_party', 'openssl', 'lib', 'libcrypto_static_{}.lib'.format(arch)),
46-
]
47+
]
4748

4849
Extension.extensions += [builder.Add(binary)]

pushbuild.txt

Lines changed: 0 additions & 6 deletions
This file was deleted.

scripting/http_test.sp

Lines changed: 91 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -2,127 +2,127 @@
22
#include <websocket>
33

44
public Plugin myinfo = {
5-
name = "HTTP Client Test",
6-
author = "ProjectSky",
7-
description = "Used for testing HTTP client",
8-
version = "1.0.0",
9-
url = "https://github.com/ProjectSky/sm-ext-websocket"
5+
name = "HTTP Client Test",
6+
author = "ProjectSky",
7+
description = "Used for testing HTTP client",
8+
version = "1.0.0",
9+
url = "https://github.com/ProjectSky/sm-ext-websocket"
1010
}
1111

1212
public void OnPluginStart()
1313
{
14-
RegServerCmd("http_get", http_get);
15-
RegServerCmd("http_post_json", http_post_json);
16-
RegServerCmd("http_post_form", http_post_form);
17-
RegServerCmd("http_put", http_put);
18-
RegServerCmd("http_patch", http_patch);
19-
RegServerCmd("http_delete", http_delete);
14+
RegServerCmd("http_get", http_get);
15+
RegServerCmd("http_post_json", http_post_json);
16+
RegServerCmd("http_post_form", http_post_form);
17+
RegServerCmd("http_put", http_put);
18+
RegServerCmd("http_patch", http_patch);
19+
RegServerCmd("http_delete", http_delete);
2020
}
2121

2222
Action http_get(int args)
2323
{
24-
HttpRequest request = new HttpRequest("https://httpbin.org/get");
25-
request.AddHeader("User-Agent", "SourceMod HTTP Client");
26-
request.Get(OnHttpResponse);
27-
return Plugin_Handled;
24+
HttpRequest request = new HttpRequest("https://httpbin.org/get");
25+
request.AddHeader("User-Agent", "SourceMod HTTP Client");
26+
request.Get(OnHttpResponse);
27+
return Plugin_Handled;
2828
}
2929

3030
Action http_post_json(int args)
3131
{
32-
HttpRequest request = new HttpRequest("https://httpbin.org/post");
33-
34-
// Create JSON payload
35-
YYJSONObject json = new YYJSONObject();
36-
json.SetString("name", "test");
37-
json.SetInt("age", 25);
38-
json.SetBool("active", true);
39-
40-
// Add custom headers
41-
request.AddHeader("User-Agent", "SourceMod HTTP Client");
42-
43-
// Send POST request with JSON body
44-
request.PostJson(json, OnHttpResponse);
45-
46-
delete json;
47-
return Plugin_Handled;
32+
HttpRequest request = new HttpRequest("https://httpbin.org/post");
33+
34+
// Create JSON payload
35+
YYJSONObject json = new YYJSONObject();
36+
json.SetString("name", "test");
37+
json.SetInt("age", 25);
38+
json.SetBool("active", true);
39+
40+
// Add custom headers
41+
request.AddHeader("User-Agent", "SourceMod HTTP Client");
42+
43+
// Send POST request with JSON body
44+
request.PostJson(json, OnHttpResponse);
45+
46+
delete json;
47+
return Plugin_Handled;
4848
}
4949

5050
Action http_post_form(int args)
5151
{
52-
HttpRequest request = new HttpRequest("https://httpbin.org/post");
53-
54-
// Add form parameters
55-
request.AppendFormParam("username", "john_doe");
56-
request.AppendFormParam("email", "john@example.com");
57-
request.AppendFormParam("age", "25");
58-
59-
// Add custom headers
60-
request.AddHeader("User-Agent", "SourceMod HTTP Client");
61-
62-
// Send POST request with form data
63-
request.PostForm(OnHttpResponse);
64-
return Plugin_Handled;
52+
HttpRequest request = new HttpRequest("https://httpbin.org/post");
53+
54+
// Add form parameters
55+
request.AppendFormParam("username", "john_doe");
56+
request.AppendFormParam("email", "john@example.com");
57+
request.AppendFormParam("age", "25");
58+
59+
// Add custom headers
60+
request.AddHeader("User-Agent", "SourceMod HTTP Client");
61+
62+
// Send POST request with form data
63+
request.PostForm(OnHttpResponse);
64+
return Plugin_Handled;
6565
}
6666

6767
Action http_put(int args)
6868
{
69-
HttpRequest request = new HttpRequest("https://httpbin.org/put");
70-
71-
// Create JSON payload for PUT
72-
YYJSONObject json = new YYJSONObject();
73-
json.SetString("id", "123");
74-
json.SetString("name", "updated_name");
75-
json.SetBool("active", false);
76-
77-
// Add custom headers
78-
request.AddHeader("User-Agent", "SourceMod HTTP Client");
79-
80-
// Send PUT request with JSON body
81-
request.PutJson(json, OnHttpResponse);
82-
83-
delete json;
84-
return Plugin_Handled;
69+
HttpRequest request = new HttpRequest("https://httpbin.org/put");
70+
71+
// Create JSON payload for PUT
72+
YYJSONObject json = new YYJSONObject();
73+
json.SetString("id", "123");
74+
json.SetString("name", "updated_name");
75+
json.SetBool("active", false);
76+
77+
// Add custom headers
78+
request.AddHeader("User-Agent", "SourceMod HTTP Client");
79+
80+
// Send PUT request with JSON body
81+
request.PutJson(json, OnHttpResponse);
82+
83+
delete json;
84+
return Plugin_Handled;
8585
}
8686

8787
Action http_patch(int args)
8888
{
89-
HttpRequest request = new HttpRequest("https://httpbin.org/patch");
90-
91-
// Create JSON payload for PATCH
92-
YYJSONObject json = new YYJSONObject();
93-
json.SetString("name", "partial_update");
94-
95-
// Add custom headers
96-
request.AddHeader("User-Agent", "SourceMod HTTP Client");
97-
98-
// Send PATCH request with JSON body
99-
request.PatchJson(json, OnHttpResponse);
100-
101-
delete json;
102-
return Plugin_Handled;
89+
HttpRequest request = new HttpRequest("https://httpbin.org/patch");
90+
91+
// Create JSON payload for PATCH
92+
YYJSONObject json = new YYJSONObject();
93+
json.SetString("name", "partial_update");
94+
95+
// Add custom headers
96+
request.AddHeader("User-Agent", "SourceMod HTTP Client");
97+
98+
// Send PATCH request with JSON body
99+
request.PatchJson(json, OnHttpResponse);
100+
101+
delete json;
102+
return Plugin_Handled;
103103
}
104104

105105
Action http_delete(int args)
106106
{
107-
HttpRequest request = new HttpRequest("https://httpbin.org/delete");
108-
request.AddHeader("User-Agent", "SourceMod HTTP Client");
109-
request.Delete(OnHttpResponse);
110-
return Plugin_Handled;
107+
HttpRequest request = new HttpRequest("https://httpbin.org/delete");
108+
request.AddHeader("User-Agent", "SourceMod HTTP Client");
109+
request.Delete(OnHttpResponse);
110+
return Plugin_Handled;
111111
}
112112

113113
void OnHttpResponse(HttpRequest http, const char[] body, int statusCode, int bodySize, any value)
114114
{
115-
// Print response details
116-
PrintToServer("Status Code: %d", statusCode);
117-
PrintToServer("Body Size: %d bytes", bodySize);
118-
119-
// Print response headers
120-
char headerValue[256];
121-
if (http.GetResponseHeader("Content-Type", headerValue, sizeof(headerValue)))
122-
{
123-
PrintToServer("Content-Type: %s", headerValue);
124-
}
125-
126-
// Print response body
127-
PrintToServer("Response Body: %s", body);
115+
// Print response details
116+
PrintToServer("Status Code: %d", statusCode);
117+
PrintToServer("Body Size: %d bytes", bodySize);
118+
119+
// Print response headers
120+
char headerValue[256];
121+
if (http.GetResponseHeader("Content-Type", headerValue, sizeof(headerValue)))
122+
{
123+
PrintToServer("Content-Type: %s", headerValue);
124+
}
125+
126+
// Print response body
127+
PrintToServer("Response Body: %s", body);
128128
}

scripting/include/websocket/ws.inc

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,48 @@ enum WebsocketType
1313
}
1414

1515
enum AddressFamily {
16-
AF_INET,
17-
AF_INET6
16+
IPV4,
17+
IPV6
1818
}
1919

2020
// Define a typeset for WebSocket callbacks
2121
typeset WebsocketCallback
2222
{
23-
// OnOpen - Called when the WebSocket connection is opened
23+
/**
24+
* OnOpen - Called when the WebSocket connection is opened
25+
* @param ws WebSocket handle
26+
*/
2427
function void (WebSocket ws);
2528

26-
// OnMessage - Called when a text message is received
29+
/**
30+
* OnMessage (STRING) - Called when a text message is received
31+
* @param ws WebSocket handle
32+
* @param message message received
33+
* @param wireSize size of the message on the wire (including null terminator)
34+
*/
2735
function void (WebSocket ws, const char[] message, int wireSize);
2836

29-
// OnMessage (JSON) - Called when a JSON message is received
37+
/**
38+
* OnMessage (JSON) - Called when a JSON message is received
39+
* @param ws WebSocket handle
40+
* @param data JSON data
41+
* @param wireSize size of the message on the wire (including null terminator)
42+
*/
3043
function void (WebSocket ws, const YYJSON data, int wireSize);
3144

32-
// OnClose - Called when the WebSocket connection is closed
45+
/**
46+
* OnClose - Called when the WebSocket connection is closed
47+
* @param ws WebSocket handle
48+
* @param code close code
49+
* @param reason reason for closure
50+
*/
3351
function void (WebSocket ws, int code, const char[] reason);
3452

35-
// OnError - Called when an error occurs with the WebSocket connection
53+
/**
54+
* OnError - Called when an error occurs with the WebSocket connection
55+
* @param ws WebSocket handle
56+
* @param errMsg error message
57+
*/
3658
function void (WebSocket ws, const char[] errMsg);
3759
}
3860

@@ -212,7 +234,7 @@ typeset WebsocketServerCallback
212234
* @param server websocket server handle
213235
* @param client websocket client handle
214236
* @param message message received
215-
* @param wireSize size of the message on the wire
237+
* @param wireSize size of the message on the wire (including null terminator)
216238
* @param RemoteAddr remote address of the client
217239
* @param RemoteId remote identifier of the client
218240
*/
@@ -254,10 +276,10 @@ methodmap WebSocketServer < Handle
254276
*
255277
* @param host host address for the server
256278
* @param port port number for the server
257-
* @param addressfamily address family to use. Defaults to AF_INET (IPv4)
279+
* @param af address family to use. Defaults to IPV4
258280
* @param pingInterval interval seconds at which the server sends ping messages to clients
259281
*/
260-
public native WebSocketServer(const char[] host, int port, AddressFamily addressfamily = AF_INET, int pingInterval = 60);
282+
public native WebSocketServer(const char[] host, int port, AddressFamily af = IPV4, int pingInterval = 60);
261283

262284
/**
263285
* Set the callback for when a message is received

0 commit comments

Comments
 (0)