Repository URL to install this package:
|
Version:
2.0.17 ▾
|
#include "psgi.h"
extern struct uwsgi_server uwsgi;
extern struct uwsgi_plugin psgi_plugin;
extern struct uwsgi_perl uperl;
XS(XS_async_sleep) {
dXSARGS;
int timeout ;
psgi_check_args(1);
struct wsgi_request *wsgi_req = current_wsgi_req();
timeout = SvIV(ST(0));
if (timeout >= 0) {
async_add_timeout(wsgi_req, timeout);
}
wsgi_req->async_force_again = 1;
XSRETURN_UNDEF;
}
XS(XS_wait_fd_read) {
dXSARGS;
int fd, timeout = 0;
psgi_check_args(1);
struct wsgi_request *wsgi_req = current_wsgi_req();
fd = SvIV(ST(0));
if (items > 1) {
timeout = SvIV(ST(1));
}
if (async_add_fd_read(wsgi_req, fd, timeout)) {
croak("unable to add fd %d to the event queue", fd);
}
wsgi_req->async_force_again = 1;
XSRETURN_UNDEF;
}
XS(XS_wait_fd_write) {
dXSARGS;
int fd, timeout = 0;
psgi_check_args(1);
struct wsgi_request *wsgi_req = current_wsgi_req();
fd = SvIV(ST(0));
if (items > 1) {
timeout = SvIV(ST(1));
}
if (async_add_fd_write(wsgi_req, fd, timeout)) {
croak("unable to add fd %d to the event queue", fd);
}
wsgi_req->async_force_again = 1;
XSRETURN_UNDEF;
}
XS(XS_signal) {
dXSARGS;
psgi_check_args(1);
uwsgi_signal_send(uwsgi.signal_socket, SvIV(ST(0)));
XSRETURN_UNDEF;
}
XS(XS_set_user_harakiri) {
dXSARGS;
psgi_check_args(1);
set_user_harakiri( SvIV(ST(0)) );
XSRETURN_UNDEF;
}
XS(XS_reload) {
dXSARGS;
psgi_check_args(0);
if (kill(uwsgi.workers[0].pid, SIGHUP)) {
uwsgi_error("kill()");
XSRETURN_NO;
}
XSRETURN_YES;
}
XS(XS_cache_set) {
dXSARGS;
char *key, *val;
STRLEN keylen;
STRLEN vallen;
uint64_t expires = 0;
char *cache = NULL;
psgi_check_args(2);
key = SvPV(ST(0), keylen);
val = SvPV(ST(1), vallen);
if (items > 2) {
expires = SvIV(ST(2));
if (items > 3) {
cache = SvPV_nolen(ST(3));
}
}
if (!uwsgi_cache_magic_set(key, (uint16_t) keylen, val, (uint64_t) vallen, expires, 0, cache)) {
XSRETURN_YES;
}
XSRETURN_UNDEF;
}
XS(XS_cache_get) {
dXSARGS;
char *key;
char *cache = NULL;
STRLEN keylen;
uint64_t vallen = 0;
psgi_check_args(1);
key = SvPV(ST(0), keylen);
if (items > 1) {
cache = SvPV_nolen(ST(1));
}
char *value = uwsgi_cache_magic_get(key, (uint16_t) keylen, &vallen, NULL, cache);
if (value) {
ST(0) = newSVpv(value, vallen);
free(value);
sv_2mortal(ST(0));
XSRETURN(1);
}
XSRETURN_UNDEF;
}
XS(XS_cache_exists) {
dXSARGS;
char *key;
char *cache = NULL;
STRLEN keylen;
psgi_check_args(1);
key = SvPV(ST(0), keylen);
if (items > 1) {
cache = SvPV_nolen(ST(1));
}
if (uwsgi_cache_magic_exists(key, (uint16_t) keylen, cache)) {
XSRETURN_YES;
}
XSRETURN_UNDEF;
}
XS(XS_cache_del) {
dXSARGS;
char *key;
char *cache = NULL;
STRLEN keylen;
psgi_check_args(1);
key = SvPV(ST(0), keylen);
if (items > 1) {
cache = SvPV_nolen(ST(1));
}
if (!uwsgi_cache_magic_del(key, (uint16_t) keylen, cache)) {
XSRETURN_YES;
}
XSRETURN_UNDEF;
}
XS(XS_cache_clear) {
dXSARGS;
char *cache = NULL;
psgi_check_args(1);
cache = SvPV_nolen(ST(0));
if (!uwsgi_cache_magic_clear(cache)) {
XSRETURN_YES;
}
XSRETURN_UNDEF;
}
XS(XS_register_signal) {
dXSARGS;
if (!uwsgi.master_process) {
XSRETURN_NO;
}
psgi_check_args(3);
uint8_t signum = SvIV(ST(0));
STRLEN kindlen;
char *kind = SvPV(ST(1), kindlen);
if (uwsgi_register_signal(signum, kind, (void *) newRV_inc(ST(2)), psgi_plugin.modifier1)) {
XSRETURN_NO;
}
XSRETURN_YES;
}
XS(XS_spooler) {
dXSARGS;
psgi_check_args(1);
uperl.spooler = (CV *) newRV_inc(ST(0));
XSRETURN_YES;
}
XS(XS_register_rpc) {
dXSARGS;
psgi_check_args(2);
char *name = SvPV_nolen(ST(0));
if (uwsgi_register_rpc(name, &psgi_plugin, 0, (void *) newRV_inc(ST(1)))) {
XSRETURN_NO;
}
XSRETURN_YES;
}
XS(XS_postfork) {
dXSARGS;
psgi_check_args(1);
uperl.postfork = newRV_inc(ST(0));
XSRETURN_YES;
}
XS(XS_atexit) {
dXSARGS;
psgi_check_args(1);
uperl.atexit = newRV_inc(ST(0));
XSRETURN_YES;
}
XS(XS_log) {
dXSARGS;
psgi_check_args(1);
uwsgi_log("%s", SvPV_nolen(ST(0)));
XSRETURN_UNDEF;
}
XS(XS_alarm) {
dXSARGS;
char *alarm;
char *msg;
STRLEN msg_len;
psgi_check_args(2);
alarm = SvPV_nolen(ST(0));
msg = SvPV(ST(1), msg_len);
uwsgi_alarm_trigger(alarm, msg, msg_len);
XSRETURN_UNDEF;
}
XS(XS_worker_id) {
dXSARGS;
psgi_check_args(0);
ST(0) = newSViv(uwsgi.mywid);
XSRETURN(1);
}
XS(XS_async_connect) {
dXSARGS;
psgi_check_args(1);
ST(0) = newSViv(uwsgi_connect(SvPV_nolen(ST(0)), 0, 1));
XSRETURN(1);
}
XS(XS_ready_fd) {
dXSARGS;
psgi_check_args(0);
struct wsgi_request *wsgi_req = current_wsgi_req();
ST(0) = newSViv(uwsgi_ready_fd(wsgi_req));
XSRETURN(1);
}
XS(XS_call) {
dXSARGS;
char *func;
uint64_t size = 0;
int i;
char *argv[256];
uint16_t argvs[256];
STRLEN arg_len;
psgi_check_args(1);
func = SvPV_nolen(ST(0));
for(i=0;i<(items-1);i++) {
argv[i] = SvPV(ST(i+1), arg_len);
argvs[i] = arg_len;
}
// response must be always freed
char *response = uwsgi_do_rpc(NULL, func, items-1, argv, argvs, &size);
if (response) {
ST(0) = newSVpv(response, size);
sv_2mortal(ST(0));
free(response);
XSRETURN(1);
}
XSRETURN_UNDEF;
}
XS(XS_rpc) {
dXSARGS;
char *node;
char *func;
uint64_t size = 0;
int i;
char *argv[256];
uint16_t argvs[256];
STRLEN arg_len;
psgi_check_args(2);
node = SvPV_nolen(ST(0));
func = SvPV_nolen(ST(1));
for(i=0;i<(items-2);i++) {
argv[i] = SvPV(ST(i+2), arg_len);
argvs[i] = arg_len;
}
// response must be always freed
char *response = uwsgi_do_rpc(node, func, items-2, argv, argvs, &size);
if (response) {
ST(0) = newSVpv(response, size);
sv_2mortal(ST(0));
free(response);
XSRETURN(1);
}
XSRETURN_UNDEF;
}
XS(XS_suspend) {
dXSARGS;
psgi_check_args(0);
struct wsgi_request *wsgi_req = current_wsgi_req();
wsgi_req->async_force_again = 0;
if (uwsgi.schedule_to_main) uwsgi.schedule_to_main(wsgi_req);
XSRETURN_UNDEF;
}
XS(XS_signal_wait) {
dXSARGS;
psgi_check_args(0);
struct wsgi_request *wsgi_req = current_wsgi_req();
int received_signal = -1;
wsgi_req->signal_received = -1;
if (items > 0) {
received_signal = uwsgi_signal_wait(SvIV(ST(0)));
}
else {
received_signal = uwsgi_signal_wait(-1);
}
if (received_signal < 0) {
XSRETURN_NO;
}
wsgi_req->signal_received = received_signal;
XSRETURN_YES;
}
#ifdef UWSGI_SSL
XS(XS_i_am_the_lord) {
dXSARGS;
psgi_check_args(1);
if (uwsgi_legion_i_am_the_lord(SvPV_nolen(ST(0)))) {
XSRETURN_YES;
}
XSRETURN_NO;
}
#endif
XS(XS_connection_fd) {
dXSARGS;
psgi_check_args(0);
struct wsgi_request *wsgi_req = current_wsgi_req();
ST(0) = newSViv(wsgi_req->fd);
sv_2mortal(ST(0));
XSRETURN(1);
}
XS(XS_websocket_handshake) {
dXSARGS;
char *key = NULL;
STRLEN key_len = 0;
char *origin = NULL;
STRLEN origin_len = 0;
char *proto = NULL;
STRLEN proto_len = 0;
psgi_check_args(0);
if (items > 0) {
key = SvPV(ST(0), key_len);
if (items > 1) {
origin = SvPV(ST(1), origin_len);
if (items > 2) {
proto = SvPV(ST(2), proto_len);
}
}
}
struct wsgi_request *wsgi_req = current_wsgi_req();
if (uwsgi_websocket_handshake(wsgi_req, key, key_len, origin, origin_len, proto, proto_len)) {
croak("unable to complete websocket handshake");
}
XSRETURN_UNDEF;
}
XS(XS_websocket_send) {
dXSARGS;
char *message = NULL;
STRLEN message_len = 0;
psgi_check_args(1);
message = SvPV(ST(0), message_len);
struct wsgi_request *wsgi_req = current_wsgi_req();
if (uwsgi_websocket_send(wsgi_req, message, message_len)) {
croak("unable to send websocket message");
}
XSRETURN_UNDEF;
}
XS(XS_websocket_send_from_sharedarea) {
dXSARGS;
psgi_check_args(2);
int id = SvIV(ST(0));
uint64_t pos = SvIV(ST(1));
uint64_t len = 0;
if (items > 2) {
len = SvIV(ST(2));
}
struct wsgi_request *wsgi_req = current_wsgi_req();
if (uwsgi_websocket_send_from_sharedarea(wsgi_req, id, pos, len)) {
croak("unable to send websocket message from sharedarea");
}
XSRETURN_UNDEF;
}
XS(XS_websocket_send_binary) {
dXSARGS;
char *message = NULL;
STRLEN message_len = 0;
psgi_check_args(1);
message = SvPV(ST(0), message_len);
struct wsgi_request *wsgi_req = current_wsgi_req();
if (uwsgi_websocket_send_binary(wsgi_req, message, message_len)) {
croak("unable to send websocket binary message");
}
XSRETURN_UNDEF;
}
XS(XS_websocket_send_binary_from_sharedarea) {
dXSARGS;
psgi_check_args(2);
int id = SvIV(ST(0));
uint64_t pos = SvIV(ST(1));
uint64_t len = 0;
if (items > 2) {
len = SvIV(ST(2));
}
struct wsgi_request *wsgi_req = current_wsgi_req();
if (uwsgi_websocket_send_binary_from_sharedarea(wsgi_req, id, pos, len)) {
croak("unable to send websocket binary message from sharedarea");
}
XSRETURN_UNDEF;
}
XS(XS_websocket_recv) {
dXSARGS;
psgi_check_args(0);
struct wsgi_request *wsgi_req = current_wsgi_req();
struct uwsgi_buffer *ub = uwsgi_websocket_recv(wsgi_req);
if (!ub) {
croak("unable to receive websocket message");
XSRETURN_UNDEF;
}
ST(0) = newSVpv(ub->buf, ub->pos);
uwsgi_buffer_destroy(ub);
sv_2mortal(ST(0));
XSRETURN(1);
}
XS(XS_websocket_recv_nb) {
dXSARGS;
psgi_check_args(0);
struct wsgi_request *wsgi_req = current_wsgi_req();
struct uwsgi_buffer *ub = uwsgi_websocket_recv_nb(wsgi_req);
if (!ub) {
croak("unable to receive websocket message");
XSRETURN_UNDEF;
}
ST(0) = newSVpv(ub->buf, ub->pos);
uwsgi_buffer_destroy(ub);
sv_2mortal(ST(0));
XSRETURN(1);
}
XS(XS_add_timer) {
dXSARGS;
psgi_check_args(2);
uint8_t uwsgi_signal = SvIV(ST(0));
int seconds = SvIV(ST(1));
if (uwsgi_add_timer(uwsgi_signal, seconds)) {
croak("unable to register timer");
XSRETURN_UNDEF;
}
XSRETURN(1);
}
XS(XS_add_rb_timer) {
dXSARGS;
psgi_check_args(2);
uint8_t uwsgi_signal = SvIV(ST(0));
int seconds = SvIV(ST(1));
if (uwsgi_signal_add_rb_timer(uwsgi_signal, seconds, 0)) {
croak("unable to register rb timer");
XSRETURN_UNDEF;
}
XSRETURN(1);
}
XS(XS_metric_inc) {
dXSARGS;
char *metric = NULL;
STRLEN metric_len = 0;
int64_t value = 1;
psgi_check_args(1);
metric = SvPV(ST(0), metric_len);
if (items > 1) {
value = (int64_t) SvIV(ST(1));
}
if (uwsgi_metric_inc(metric, NULL, value)) {
croak("unable to update metric");
XSRETURN_UNDEF;
}
XSRETURN_YES;
}
XS(XS_metric_dec) {
dXSARGS;
char *metric = NULL;
STRLEN metric_len = 0;
int64_t value = 1;
psgi_check_args(1);
metric = SvPV(ST(0), metric_len);
if (items > 1) {
value = (int64_t) SvIV(ST(1));
}
if (uwsgi_metric_dec(metric, NULL, value)) {
croak("unable to update metric");
XSRETURN_UNDEF;
}
XSRETURN_YES;
}
XS(XS_metric_mul) {
dXSARGS;
char *metric = NULL;
STRLEN metric_len = 0;
int64_t value = 1;
psgi_check_args(1);
metric = SvPV(ST(0), metric_len);
if (items > 1) {
value = (int64_t) SvIV(ST(1));
}
if (uwsgi_metric_mul(metric, NULL, value)) {
croak("unable to update metric");
XSRETURN_UNDEF;
}
XSRETURN_YES;
}
XS(XS_metric_div) {
dXSARGS;
char *metric = NULL;
STRLEN metric_len = 0;
int64_t value = 1;
psgi_check_args(1);
metric = SvPV(ST(0), metric_len);
if (items > 1) {
value = (int64_t) SvIV(ST(1));
}
if (uwsgi_metric_div(metric, NULL, value)) {
croak("unable to update metric");
XSRETURN_UNDEF;
}
XSRETURN_YES;
}
XS(XS_metric_set) {
dXSARGS;
char *metric = NULL;
STRLEN metric_len = 0;
int64_t value = 0;
psgi_check_args(2);
metric = SvPV(ST(0), metric_len);
value = (int64_t) SvIV(ST(1));
if (uwsgi_metric_set(metric, NULL, value)) {
croak("unable to update metric");
XSRETURN_UNDEF;
}
XSRETURN_YES;
}
XS(XS_metric_get) {
dXSARGS;
char *metric = NULL;
STRLEN metric_len = 0;
psgi_check_args(1);
metric = SvPV(ST(0), metric_len);
ST(0) = newSViv(uwsgi_metric_get(metric, NULL));
sv_2mortal(ST(0));
XSRETURN(1);
}
XS(XS_sharedarea_wait) {
dXSARGS;
int id;
int freq = 0;
int timeout = 0;
psgi_check_args(1);
id = SvIV(ST(0));
if (items > 1) {
freq = SvIV(ST(1));
if (items > 2) {
timeout = SvIV(ST(2));
}
}
if (uwsgi_sharedarea_wait(id, freq, timeout)) {
croak("unable to wait for sharedarea %d", id);
XSRETURN_UNDEF;
}
XSRETURN_YES;
}
XS(XS_sharedarea_read) {
dXSARGS;
int id;
uint64_t pos;
uint64_t len = 0;
psgi_check_args(2);
id = SvIV(ST(0));
pos = SvIV(ST(1));
if (items > 2) {
len = SvIV(ST(2));
}
else {
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
if (!sa) {
croak("unable to read from sharedarea %d", id);
XSRETURN_UNDEF;
}
len = (sa->max_pos+1)-pos;
}
char *buf = uwsgi_malloc(len);
int64_t rlen = uwsgi_sharedarea_read(id, pos, buf, len);
if (rlen < 0) {
free(buf);
croak("unable to read from sharedarea %d", id);
XSRETURN_UNDEF;
}
ST(0) = sv_newmortal();
sv_usepvn(ST(0), buf, rlen);
XSRETURN(1);
}
XS(XS_sharedarea_readfast) {
dXSARGS;
int id;
uint64_t pos;
uint64_t len = 0;
psgi_check_args(3);
id = SvIV(ST(0));
pos = SvIV(ST(1));
char *buf = SvPV_nolen(ST(2));
if (items > 3) {
len = SvIV(ST(3));
}
if (uwsgi_sharedarea_read(id, pos, buf, len)) {
croak("unable to (fast) read from sharedarea %d", id);
XSRETURN_UNDEF;
}
XSRETURN_YES;
}
XS(XS_sharedarea_write) {
dXSARGS;
int id;
uint64_t pos;
STRLEN vallen;
psgi_check_args(3);
id = SvIV(ST(0));
pos = SvIV(ST(1));
char *value = SvPV(ST(2), vallen);
if (uwsgi_sharedarea_write(id, pos, value, vallen)) {
croak("unable to write to sharedarea %d", id);
XSRETURN_UNDEF;
}
XSRETURN_YES;
}
XS(XS_chunked_read) {
dXSARGS;
int timeout = 0;
size_t len = 0;
psgi_check_args(0);
if (items > 0) {
timeout = SvIV(ST(0));
}
struct wsgi_request *wsgi_req = current_wsgi_req();
char *chunk = uwsgi_chunked_read(wsgi_req, &len, timeout, 0);
if (!chunk) {
croak("unable to receive chunked part");
XSRETURN_UNDEF;
}
ST(0) = newSVpv(chunk, len);
sv_2mortal(ST(0));
XSRETURN(1);
}
XS(XS_chunked_read_nb) {
dXSARGS;
size_t len = 0;
psgi_check_args(0);
struct wsgi_request *wsgi_req = current_wsgi_req();
char *chunk = uwsgi_chunked_read(wsgi_req, &len, 0, 1);
if (!chunk) {
if (uwsgi_is_again()) XSRETURN_UNDEF;
croak("unable to receive chunked part");
XSRETURN_UNDEF;
}
ST(0) = newSVpv(chunk, len);
sv_2mortal(ST(0));
XSRETURN(1);
}
XS(XS_spool) {
dXSARGS;
psgi_check_args(1);
SV *arg = ST(0);
HV *env = NULL;
char *body = NULL;
STRLEN body_len = 0;
if (SvROK(arg)) {
env = (HV *) SvRV(arg);
}
else {
croak("spool argument must be a hashref");
XSRETURN_UNDEF;
}
if (SvTYPE(env) != SVt_PVHV) {
croak("spool argument must be a hashref");
XSRETURN_UNDEF;
}
if (hv_exists(env, "body", 4)) {
SV **body_sv = hv_fetch(env, "body", 4, 0);
body = SvPV(*body_sv, body_len);
(void)hv_delete(env, "body", 4, 0);
}
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
HE *he;
hv_iterinit(env);
while((he = hv_iternext(env))) {
I32 klen;
STRLEN vlen;
char *key = hv_iterkey(he, &klen);
char *value = SvPV(hv_iterval(env, he), vlen);
if (uwsgi_buffer_append_keyval(ub, key, klen, value, vlen)) {
croak("unable to serialize hash to spool file");
uwsgi_buffer_destroy(ub);
XSRETURN_UNDEF;
}
}
char *filename = uwsgi_spool_request(NULL, ub->buf, ub->pos, body, body_len);
uwsgi_buffer_destroy(ub);
if (filename) {
ST(0) = newSVpv(filename, strlen(filename));
free(filename);
XSRETURN(1);
}
croak("unable to spool request");
XSRETURN_UNDEF;
}
XS(XS_add_var) {
dXSARGS;
psgi_check_args(2);
struct wsgi_request *wsgi_req = current_wsgi_req();
STRLEN keylen;
char *key = SvPV(ST(0), keylen);
STRLEN vallen;
char *val = SvPV(ST(1), vallen);
if (!uwsgi_req_append(wsgi_req, key, keylen, val, vallen)) {
croak("unable to add request var, check your buffer size");
XSRETURN_UNDEF;
}
XSRETURN_YES;
}
void init_perl_embedded_module() {
psgi_xs(reload);
psgi_xs(cache_get);
psgi_xs(cache_exists);
psgi_xs(cache_set);
psgi_xs(cache_del);
psgi_xs(cache_clear);
psgi_xs(call);
psgi_xs(rpc);
psgi_xs(wait_fd_read);
psgi_xs(wait_fd_write);
psgi_xs(async_sleep);
psgi_xs(ready_fd);
psgi_xs(log);
psgi_xs(async_connect);
psgi_xs(suspend);
psgi_xs(signal);
psgi_xs(register_signal);
psgi_xs(register_rpc);
psgi_xs(signal_wait);
#ifdef UWSGI_SSL
psgi_xs(i_am_the_lord);
#endif
psgi_xs(connection_fd);
psgi_xs(alarm);
psgi_xs(websocket_handshake);
psgi_xs(websocket_recv);
psgi_xs(websocket_recv_nb);
psgi_xs(websocket_send);
psgi_xs(websocket_send_from_sharedarea);
psgi_xs(websocket_send_binary);
psgi_xs(websocket_send_binary_from_sharedarea);
psgi_xs(postfork);
psgi_xs(atexit);
psgi_xs(add_timer);
psgi_xs(add_rb_timer);
psgi_xs(set_user_harakiri);
psgi_xs(metric_inc);
psgi_xs(metric_dec);
psgi_xs(metric_mul);
psgi_xs(metric_div);
psgi_xs(metric_get);
psgi_xs(metric_set);
psgi_xs(chunked_read);
psgi_xs(chunked_read_nb);
psgi_xs(sharedarea_read);
psgi_xs(sharedarea_readfast);
psgi_xs(sharedarea_write);
psgi_xs(sharedarea_wait);
psgi_xs(spooler);
psgi_xs(spool);
psgi_xs(add_var);
psgi_xs(worker_id);
}