The Perl and Raku Conference 2025: Greenville, South Carolina - June 27-29 Learn more

#include "nlws.h"
#include "nlws_perl_loop.h"
#include "xshelper/xshelper.h"
#define DEBUG 0
#if DEBUG
#define LOG_FUNC fprintf(stderr, "%s\n", __func__)
#else
#define LOG_FUNC
#endif
static int
init_pt_custom (struct lws_context *cx, void *_loop, int tsi) {
LOG_FUNC;
nlws_abstract_loop_t* myloop_p = lws_evlib_tsi_to_evlib_pt(cx, tsi);
nlws_abstract_loop_t *sourceloop_p = _loop;
PERL_CONTEXT_FROM_STRUCT(sourceloop_p);
SV* methargs[] = {
newSVuv( (UV) cx ),
NULL,
};
xsh_call_object_method_void( aTHX_ sourceloop_p->perlobj, "set_lws_context", methargs );
StructCopy(sourceloop_p, myloop_p, nlws_abstract_loop_t);
myloop_p->lws_context = cx;
SvREFCNT_inc(myloop_p->perlobj);
return 0;
}
static int
custom_io_accept (struct lws *wsi) {
LOG_FUNC;
nlws_abstract_loop_t* myloop_p = lws_evlib_wsi_to_evlib_pt(wsi);
PERL_CONTEXT_FROM_STRUCT(myloop_p);
int fd = lws_get_socket_fd(wsi);
SV* myloop_sv = myloop_p->perlobj;
SV* args[] = { newSViv(fd), NULL };
xsh_call_object_method_void(aTHX_ myloop_sv, "add_fd", args);
return 0;
}
static void
custom_io (struct lws *wsi, unsigned int flags) {
LOG_FUNC;
nlws_abstract_loop_t* myloop_p = lws_evlib_wsi_to_evlib_pt(wsi);
int fd = lws_get_socket_fd(wsi);
if (-1 != fd) {
PERL_CONTEXT_FROM_STRUCT(myloop_p);
SV* myloop_sv = myloop_p->perlobj;
char *method_name;
if (flags & LWS_EV_START) {
method_name = "add_to_fd";
}
else {
method_name = "remove_from_fd";
}
SV* args[] = {
newSViv(fd),
newSVuv(flags),
NULL,
};
xsh_call_object_method_void(aTHX_ myloop_sv, method_name, args );
}
}
static int
custom_io_close (struct lws *wsi) {
LOG_FUNC;
nlws_abstract_loop_t* myloop_p = lws_evlib_wsi_to_evlib_pt(wsi);
int fd = lws_get_socket_fd(wsi);
if (-1 != fd) {
PERL_CONTEXT_FROM_STRUCT(myloop_p);
SV* myloop_sv = myloop_p->perlobj;
SV* args[] = { newSViv(fd), NULL };
xsh_call_object_method_void(aTHX_ myloop_sv, "remove_fd", args);
}
return 0;
}
# if 0
static void
custom_destroy_wsi (struct lws *wsi) {
LOG_FUNC;
nlws_abstract_loop_t* myloop_p = lws_evlib_wsi_to_evlib_pt(wsi);
PERL_CONTEXT_FROM_STRUCT(myloop_p);
}
static void
custom_destroy_context1 (struct lws_context *context) {
LOG_FUNC;
fprintf(stderr, "lws_context = %p\n", context);
}
static void
custom_destroy_context2 (struct lws_context *context) {
LOG_FUNC;
fprintf(stderr, "lws_context = %p\n", context);
}
#endif
static void
custom_destroy_pt (struct lws_context *cx, int tsi) {
LOG_FUNC;
nlws_abstract_loop_t* myloop_p = lws_evlib_tsi_to_evlib_pt(cx, tsi);
PERL_CONTEXT_FROM_STRUCT(myloop_p);
SvREFCNT_dec(myloop_p->perlobj);
}
const struct lws_event_loop_ops event_loop_ops_custom = {
.name = "net-lws-custom-loop",
.init_pt = init_pt_custom,
.init_vhost_listen_wsi = custom_io_accept,
.sock_accept = custom_io_accept,
.io = custom_io,
.wsi_logical_close = custom_io_close,
# if 0
.destroy_wsi = custom_destroy_wsi,
.destroy_context1 = custom_destroy_context1,
.destroy_context2 = custom_destroy_context2,
#endif
.destroy_pt = custom_destroy_pt,
.evlib_size_pt = sizeof(nlws_abstract_loop_t),
};
const lws_plugin_evlib_t evlib_custom = {
.hdr = {
"custom perl loop",
"net_lws_plugin",
LWS_BUILD_HASH,
LWS_PLUGIN_API_MAGIC,
},
.ops = &event_loop_ops_custom,
};