aboutsummaryrefslogtreecommitdiff
path: root/packages/bun-uws/capi/examples/Broadcast.c
blob: ef1b091018479a063b8aaccb0ac25d8fef1aaf8c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#include "../libuwebsockets.h"
#include <stdio.h>
#include <malloc.h>
#include <time.h>
#include <string.h>
#include <stdarg.h>
#define SSL 1


//Timer close helper
void uws_timer_close(struct us_timer_t *timer)
{
    struct us_timer_t *t = (struct us_timer_t *)timer;
    struct timer_handler_data *data;
    memcpy(&data, us_timer_ext(t), sizeof(struct timer_handler_data *));
    free(data);
    us_timer_close(t, 0);
}
//Timer create helper
struct us_timer_t *uws_create_timer(int ms, int repeat_ms, void (*handler)(void *data), void *data)
{
    struct us_loop_t *loop = uws_get_loop();
    struct us_timer_t *delayTimer = us_create_timer(loop, 0, sizeof(void *));

    struct timer_handler_data
    {
        void *data;
        void (*handler)(void *data);
        bool repeat;
    };

    struct timer_handler_data *timer_data = (struct timer_handler_data *)malloc(sizeof(timer_handler_data));
    timer_data->data = data;
    timer_data->handler = handler;
    timer_data->repeat = repeat_ms > 0;
    memcpy(us_timer_ext(delayTimer), &timer_data, sizeof(struct timer_handler_data *));

    us_timer_set(
        delayTimer, [](struct us_timer_t *t)
        {
            /* We wrote the pointer to the timer's extension */
            struct timer_handler_data *data;
            memcpy(&data, us_timer_ext(t), sizeof(struct timer_handler_data *));

            data->handler(data->data);

            if (!data->repeat)
            {
                free(data);
                us_timer_close(t, 0);
            }
        },
        ms, repeat_ms);

    return (struct us_timer_t *)delayTimer;
}

/* This is a simple WebSocket "sync" upgrade example.
 * You may compile it with "WITH_OPENSSL=1 make" or with "make" */

/* ws->getUserData returns one of these */
struct PerSocketData {
    /* Fill with user data */
};

int buffer_size(const char* format, ...) {
    va_list args;
    va_start(args, format);
    int result = vsnprintf(NULL, 0, format, args);
    va_end(args);
    return result + 1; // safe byte for \0
}

void listen_handler(struct us_listen_socket_t *listen_socket, uws_app_listen_config_t config,  void* user_data)
{
    if (listen_socket){
        printf("Listening on port wss://localhost:%d\n", config.port);
    }
}

void open_handler(uws_websocket_t* ws){

     /* Open event here, you may access uws_ws_get_user_data(WS) which points to a PerSocketData struct */
    uws_ws_subscribe(SSL, ws, "broadcast", 9);
}

void message_handler(uws_websocket_t* ws, const char* message, size_t length, uws_opcode_t opcode){
}

void close_handler(uws_websocket_t* ws, int code, const char* message, size_t length){
    /* You may access uws_ws_get_user_data(ws) here, but sending or
     * doing any kind of I/O with the socket is not valid. */
}

void drain_handler(uws_websocket_t* ws){
    /* Check uws_ws_get_buffered_amount(ws) here */
}

void ping_handler(uws_websocket_t* ws, const char* message, size_t length){
    /* You don't need to handle this one, we automatically respond to pings as per standard */
}

void pong_handler(uws_websocket_t* ws, const char* message, size_t length){

    /* You don't need to handle this one either */
}

void on_timer_interval(void* data){

    // broadcast the unix time as millis

    uws_app_t * app = (uws_app_t *)data;
    struct timespec ts;
    timespec_get(&ts, TIME_UTC);

    int64_t millis = ts.tv_sec * 1000 + ts.tv_nsec / 1000000;

    
    char* message = (char*)malloc((size_t)buffer_size("%ld", millis));
    size_t message_length = sprintf(message, "%ld", millis);

    uws_publish(SSL, app, "broadcast", 9, message, message_length, uws_opcode_t::TEXT, false);
    free(message);
}

int main()
{


    uws_app_t *app = uws_create_app(SSL, (struct us_socket_context_options_t){
        /* There are example certificates in uWebSockets.js repo */
	    .key_file_name = "../misc/key.pem",
	    .cert_file_name = "../misc/cert.pem",
	    .passphrase = "1234"
    });

	uws_ws(SSL, app, "/*", (uws_socket_behavior_t){
		.compression = uws_compress_options_t::SHARED_COMPRESSOR,
        .maxPayloadLength = 16 * 1024,
        .idleTimeout = 12,
        .maxBackpressure = 1 * 1024 * 1024,
		.upgrade = NULL,
        .open = open_handler,
        .message = message_handler,
        .drain = drain_handler,
        .ping = ping_handler,
        .pong = pong_handler,
        .close = close_handler,
	});

    uws_app_listen(SSL, app, 9001, listen_handler, NULL);

    // broadcast the unix time as millis every 8 millis
    uws_create_timer(8, 8, on_timer_interval,  app);

	uws_app_run(SSL, app);
}