Skip to content

Instantly share code, notes, and snippets.

@gesslar
Created July 1, 2024 00:12
Show Gist options
  • Save gesslar/4cfba19c33b66b675cc63906f8354419 to your computer and use it in GitHub Desktop.
Save gesslar/4cfba19c33b66b675cc63906f8354419 to your computer and use it in GitHub Desktop.
Basic example of using websocket to connect to echo.websocket.org (https://echo.websocket.org/)
// /adm/daemons/websocket_echo.c
// Test websocket with echo.websocket.org
//
// Created: 2024/06/30: Gesslar
// Last Change: 2024/06/30: Gesslar
//
// 2024/06/30: Gesslar - Created
#include <daemons.h>
#include <websocket.h>
#include <net/socket.h>
#include <net/socket_errors.h>
inherit WEBSOCKET_D ;
private nosave mapping handles = ([ ]) ;
private nosave string host = "echo.websocket.org" ;
private nosave string path = UNDEFINED ;
private nosave string server_name = "WebSocket Echo Server" ;
void periodic_message(int fd) ;
void send_outgoing_message(int fd, string message) ;
void close_down_session(int fd) ;
void setup() {
log_level = 1 ;
}
// Start the Connection
varargs void startup() {
ws_connect(host, path) ;
}
void handle_connected(int fd) {
mapping curr = ([ ]) ;
int closing_time = 15+random(15) ;
curr["host"] = ws_get_host(fd) ;
curr["port"] = ws_get_port(fd) ;
_log(2, "Scheduling periodic messaging") ;
curr["messaging"] = call_out_walltime((: periodic_message, fd :), 5) ;
_log(2, "Scheduling close down in %d seconds", closing_time) ;
curr["closing"] = call_out_walltime((: close_down_session, fd :), closing_time) ;
handles[fd] = curr ;
}
void handle_shutdown(int fd, mapping info) {
mapping curr ;
int messaging, closing ;
if(!handles[fd]) {
_log(2, "No handle for fd %d\n", fd) ;
return ;
}
messaging = handles[fd]["messaging"] ;
if(!nullp(messaging)) {
if(find_call_out(messaging) != -1) {
_log(1, "Stopping automatic messaging") ;
remove_call_out(messaging) ;
}
}
closing = handles[fd]["closing"] ;
if(!nullp(closing)) {
if(find_call_out(closing) != -1) {
_log(1, "Stopping automatic close down") ;
remove_call_out(closing) ;
}
}
curr = handles[fd] ;
map_delete(handles, fd);
}
// Function to parse text frames
void handle_text_frame(int fd, mapping frame_info) {
string payload ;
mixed message ;
if(!frame_info) {
_log(2, "No frame info\n") ;
return ;
}
payload = to_string(frame_info["payload"]);
message = REST_D->determine_response_payload(payload) ;
if(!stringp(message)) {
_log(2, "Received non-string payload: %O\n", message) ;
return ;
}
_log(1, "Received message: %O\n", message) ;
}
void periodic_message(int fd) {
int messaging = handles[fd]["messaging"] ;
if(find_call_out(messaging) != -1) {
_log(1, "Canceling existing messaging schedule") ;
remove_call_out(messaging) ;
}
_log(2, "Sending periodic message") ;
send_outgoing_message(fd, "Hello, world - " + base64encode(""+time())) ;
_log(2, "Scheduling next message") ;
handles[fd]["messaging"] = call_out_walltime((: periodic_message, fd :), 10+random(20)) ;
}
void send_outgoing_message(int fd, string message) {
_log(1, "Sending message: %O\n", message) ;
if(!send_message(fd, WS_TEXT_FRAME, message))
_log(1, "Failed to send message") ;
}
void close_down_session(int fd) {
_log(1, "Automatically closing down session") ;
if(!send_message(fd, WS_CLOSE_FRAME, WS_CLOSE_NORMAL, "Self-initiated close down"))
_log(1, "Failed to send close frame") ;
}
2024/06/30 17:32:21 ws_connect - Setting up socket
2024/06/30 17:32:21 ws_on_resolve - Host Resolved Host: echo.websocket.org, Addr: 66.241.124.119
2024/06/30 17:32:21 ws_on_resolve - Connecting to echo.websocket.org
2024/06/30 17:32:21 ws_write_data - Socket fully connected, now able to send data
2024/06/30 17:32:21 ws_write_data - Handshake request sent
2024/06/30 17:32:21 ws_receive_data - =========== STARTING WS TRANSACTION 1 ===========
2024/06/30 17:32:21 ws_receive_data - Incoming size: 266
2024/06/30 17:32:21 ws_receive_data - Buffer size: 266
2024/06/30 17:32:21 Ok listen: ({ 15, "LISTEN", "STREAM", "*.8282", "", OBJ(/adm/daemons/rest) })
2024/06/30 17:32:21 ws_receive_data - Headers processed. Remaining buffer size: 0
2024/06/30 17:32:21 handle_handshake - ===== VALIDATING WEBSOCKET HANDSHAKE =====
2024/06/30 17:32:21 handle_handshake - HTTP Status Code: 101
2024/06/30 17:32:21 handle_handshake - Header 'upgrade': websocket
2024/06/30 17:32:21 handle_handshake - Header 'Connection': upgrade
2024/06/30 17:32:21 handle_handshake - Generated Key: C9KmJmLjIeZrgmQj
2024/06/30 17:32:21 handle_handshake - Base64 Encoded SHA-1 Hash (Expected): AfLYkK4OpeKucLEadA4pX2f6qYg=
2024/06/30 17:32:21 handle_handshake - Header 'sec-websocket-accept': AfLYkK4OpeKucLEadA4pX2f6qYg=
2024/06/30 17:32:21 handle_handshake - ===== WEBSOCKET HANDSHAKE SUCCESS =====
2024/06/30 17:32:21 handle_connected - Connected to WebSocket Echo Server
2024/06/30 17:32:21 handle_connected - Scheduling periodic messaging
2024/06/30 17:32:21 handle_connected - Sheduling close down in 24 seconds
2024/06/30 17:32:21 ws_receive_data - =========== STARTING WS TRANSACTION 2 ===========
2024/06/30 17:32:21 ws_receive_data - Incoming size: 34
2024/06/30 17:32:21 ws_receive_data - Buffer size: 34
2024/06/30 17:32:21 ws_receive_data - Processing WebSocket data
2024/06/30 17:32:21 is_message_complete - Enough data for the full payload
2024/06/30 17:32:21 parse_websocket_frame - Initial frame details - fin: 128, opcode: 1, masked: 0, payload_length: 32
2024/06/30 17:32:21 parse_websocket_frame - Processed payload length: 32, offset: 2
2024/06/30 17:32:21 parse_websocket_frame - Payload unmasked or copied
2024/06/30 17:32:21 parse_websocket_frame - Offset: 2, Payload Length: 32, Buffer Size: 34
2024/06/30 17:32:21 parse_websocket_frame - Remaining buffer size: 0
2024/06/30 17:32:21 process_websocket - Received text frame: Request served by 7811941c69e658
2024/06/30 17:32:21 process_text_frame - Payload: Request served by 7811941c69e658
2024/06/30 17:32:21 handle_text_frame - Received text frame: "Request served by 7811941c69e658"
2024/06/30 17:32:26 periodic_message - Sending periodic message
2024/06/30 17:32:26 send_message - Frame type: 1, Message: ({ /* sizeof() == 1 */
"Hello, world - MTcxOTc4MzE0Ng=="
})
2024/06/30 17:32:26 send_message - Binary frame: "0x81, 0x9f, 0x7f, 0x51, 0x17, 0xa5, 0x37, 0x34, 0x7b, 0xc9, 0x10, 0x7d, 0x37, 0xd2, 0x10, 0x23, 0x7b, 0xc1, 0x5f, 0x7c, 0x37, 0xe8, 0x2b, 0x32, 0x6f, 0xea, 0x2b, 0x32, 0x23, 0xe8, 0x05, 0x14, 0x27, 0xeb, 0x18, 0x6c, 0x2a"
2024/06/30 17:32:26 send_message - Sent message to echo.websocket.org
2024/06/30 17:32:26 periodic_message - Scheduling next message
2024/06/30 17:32:26 ws_receive_data - =========== STARTING WS TRANSACTION 3 ===========
2024/06/30 17:32:26 ws_receive_data - Incoming size: 33
2024/06/30 17:32:26 ws_receive_data - Buffer size: 33
2024/06/30 17:32:26 ws_receive_data - Processing WebSocket data
2024/06/30 17:32:26 is_message_complete - Enough data for the full payload
2024/06/30 17:32:26 parse_websocket_frame - Initial frame details - fin: 128, opcode: 1, masked: 0, payload_length: 31
2024/06/30 17:32:26 parse_websocket_frame - Processed payload length: 31, offset: 2
2024/06/30 17:32:26 parse_websocket_frame - Payload unmasked or copied
2024/06/30 17:32:26 parse_websocket_frame - Offset: 2, Payload Length: 31, Buffer Size: 33
2024/06/30 17:32:26 parse_websocket_frame - Remaining buffer size: 0
2024/06/30 17:32:26 process_websocket - Received text frame: Hello, world - MTcxOTc4MzE0Ng==
2024/06/30 17:32:26 process_text_frame - Payload: Hello, world - MTcxOTc4MzE0Ng==
2024/06/30 17:32:26 handle_text_frame - Received text frame: "Hello, world - MTcxOTc4MzE0Ng=="
2024/06/30 17:32:45 close_down_session - Closing down session
2024/06/30 17:32:45 send_message - Frame type: 8, Message: ({ /* sizeof() == 2 */
1000,
"Self-initiated close down"
})
2024/06/30 17:32:45 send_message - Binary frame: "0x88, 0x9b, 0xa9, 0x88, 0xf0, 0x8b, 0xaa, 0x60, 0xa3, 0xee, 0xc5, 0xee, 0xdd, 0xe2, 0xc7, 0xe1, 0x84, 0xe2, 0xc8, 0xfc, 0x95, 0xef, 0x89, 0xeb, 0x9c, 0xe4, 0xda, 0xed, 0xd0, 0xef, 0xc6, 0xff, 0x9e"
2024/06/30 17:32:45 send_message - Sent message to echo.websocket.org
2024/06/30 17:32:45 ws_receive_data - =========== STARTING WS TRANSACTION 4 ===========
2024/06/30 17:32:45 ws_receive_data - Incoming size: 4
2024/06/30 17:32:45 ws_receive_data - Buffer size: 4
2024/06/30 17:32:45 ws_receive_data - Processing WebSocket data
2024/06/30 17:32:45 is_message_complete - Enough data for the full payload
2024/06/30 17:32:45 parse_websocket_frame - Initial frame details - fin: 128, opcode: 8, masked: 0, payload_length: 2
2024/06/30 17:32:45 parse_websocket_frame - Processed payload length: 2, offset: 2
2024/06/30 17:32:45 parse_websocket_frame - Payload unmasked or copied
2024/06/30 17:32:45 parse_websocket_frame - Offset: 2, Payload Length: 2, Buffer Size: 4
2024/06/30 17:32:45 parse_websocket_frame - Remaining buffer size: 0
2024/06/30 17:32:45 process_websocket - Received close frame: "0x03, 0xe8"
2024/06/30 17:32:45 process_close_frame - Connection closed by server. Code: 1000, Reason:
2024/06/30 17:32:45 handle_shutdown - Stopping automatic messaging
2024/06/30 17:32:45 ws_socket_shutdown - Shutting down socket after 24.43 seconds
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment