mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-16 01:20:12 +00:00
180 lines
4.2 KiB
C
180 lines
4.2 KiB
C
#include <uwsgi.h>
|
|
|
|
extern struct uwsgi_server uwsgi;
|
|
|
|
int uwsgi_register_rpc(char *name, struct uwsgi_plugin *plugin, uint8_t args, void *func) {
|
|
|
|
struct uwsgi_rpc *urpc;
|
|
int ret = -1;
|
|
|
|
if (uwsgi.mywid == 0 && uwsgi.workers[0].pid != uwsgi.mypid) {
|
|
uwsgi_log("only the master and the workers can register RPC functions\n");
|
|
return -1;
|
|
}
|
|
|
|
uwsgi_lock(uwsgi.rpc_table_lock);
|
|
|
|
// first check if a function is already registered
|
|
size_t i;
|
|
for(i=0;i<uwsgi.shared->rpc_count[uwsgi.mywid];i++) {
|
|
int pos = (uwsgi.mywid * uwsgi.rpc_max) + i;
|
|
urpc = &uwsgi.rpc_table[pos];
|
|
if (!strcmp(name, urpc->name)) {
|
|
goto already;
|
|
}
|
|
}
|
|
|
|
if (uwsgi.shared->rpc_count[uwsgi.mywid] < uwsgi.rpc_max) {
|
|
int pos = (uwsgi.mywid * uwsgi.rpc_max) + uwsgi.shared->rpc_count[uwsgi.mywid];
|
|
urpc = &uwsgi.rpc_table[pos];
|
|
uwsgi.shared->rpc_count[uwsgi.mywid]++;
|
|
already:
|
|
memcpy(urpc->name, name, strlen(name));
|
|
urpc->plugin = plugin;
|
|
urpc->args = args;
|
|
urpc->func = func;
|
|
urpc->shared = uwsgi.mywid == 0 ? 1 : 0;
|
|
|
|
ret = 0;
|
|
if (uwsgi.mywid == 0) {
|
|
uwsgi_log("registered shared/inherited RPC function \"%s\"\n", name);
|
|
}
|
|
else {
|
|
uwsgi_log("registered RPC function \"%s\" on worker %d\n", name, uwsgi.mywid);
|
|
}
|
|
}
|
|
|
|
// implement cow
|
|
if (uwsgi.mywid == 0) {
|
|
int i;
|
|
for(i=1;i<=uwsgi.numproc;i++) {
|
|
uwsgi.shared->rpc_count[i] = uwsgi.shared->rpc_count[0];
|
|
int pos = (i * uwsgi.rpc_max);
|
|
memcpy(&uwsgi.rpc_table[pos], uwsgi.rpc_table, sizeof(struct uwsgi_rpc) * uwsgi.rpc_max);
|
|
}
|
|
}
|
|
|
|
uwsgi_unlock(uwsgi.rpc_table_lock);
|
|
|
|
return ret;
|
|
}
|
|
|
|
uint16_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], uint16_t argvs[], char *output) {
|
|
|
|
struct uwsgi_rpc *urpc = NULL;
|
|
uint64_t i;
|
|
uint16_t ret = 0;
|
|
|
|
int pos = (uwsgi.mywid * uwsgi.rpc_max);
|
|
|
|
for (i = 0; i < uwsgi.shared->rpc_count[uwsgi.mywid]; i++) {
|
|
if (uwsgi.rpc_table[pos + i].name[0] != 0) {
|
|
if (!strcmp(uwsgi.rpc_table[pos + i].name, name)) {
|
|
urpc = &uwsgi.rpc_table[pos + i];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (urpc) {
|
|
if (urpc->plugin->rpc) {
|
|
ret = urpc->plugin->rpc(urpc->func, argc, argv, argvs, output);
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t argvs[], uint16_t * len) {
|
|
|
|
uint8_t i;
|
|
uint16_t ulen;
|
|
struct uwsgi_header *uh = NULL;
|
|
char *buffer = NULL;
|
|
|
|
*len = 0;
|
|
|
|
if (node == NULL || !strcmp(node, "")) {
|
|
// allocate the whole buffer
|
|
buffer = uwsgi_malloc(UMAX16);
|
|
*len = uwsgi_rpc(func, argc, argv, argvs, buffer);
|
|
return buffer;
|
|
}
|
|
|
|
|
|
// connect to node (async way)
|
|
int fd = uwsgi_connect(node, 0, 1);
|
|
if (fd < 0)
|
|
return NULL;
|
|
|
|
// wait for connection;
|
|
int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
|
if (ret <= 0) {
|
|
close(fd);
|
|
return NULL;
|
|
}
|
|
|
|
// prepare a uwsgi array
|
|
uint16_t buffer_size = 2 + strlen(func);
|
|
|
|
for (i = 0; i < argc; i++) {
|
|
buffer_size += 2 + argvs[i];
|
|
}
|
|
|
|
// allocate the whole buffer
|
|
buffer = uwsgi_malloc(4+buffer_size);
|
|
|
|
// set the uwsgi header
|
|
uh = (struct uwsgi_header *) buffer;
|
|
uh->modifier1 = 173;
|
|
uh->pktsize = buffer_size;
|
|
uh->modifier2 = 0;
|
|
|
|
// add func to the array
|
|
char *bufptr = buffer + 4;
|
|
ulen = strlen(func);
|
|
*bufptr++ = (uint8_t) (ulen & 0xff);
|
|
*bufptr++ = (uint8_t) ((ulen >> 8) & 0xff);
|
|
memcpy(bufptr, func, ulen);
|
|
bufptr += ulen;
|
|
|
|
for (i = 0; i < argc; i++) {
|
|
ulen = argvs[i];
|
|
*bufptr++ = (uint8_t) (ulen & 0xff);
|
|
*bufptr++ = (uint8_t) ((ulen >> 8) & 0xff);
|
|
memcpy(bufptr, argv[i], ulen);
|
|
bufptr += ulen;
|
|
}
|
|
|
|
// ok the reuqest is ready, let's send it in non blocking way
|
|
if (uwsgi_write_true_nb(fd, buffer, buffer_size+4, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
|
goto error;
|
|
}
|
|
|
|
// ok time to wait for the response in non blocking way
|
|
size_t rlen = buffer_size+4;
|
|
if (uwsgi_read_with_realloc(fd, &buffer, &rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
|
goto error;
|
|
}
|
|
|
|
close(fd);
|
|
*len = rlen;
|
|
if (*len == 0) {
|
|
goto error;
|
|
}
|
|
return buffer;
|
|
|
|
error:
|
|
close(fd);
|
|
free(buffer);
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
void uwsgi_rpc_init() {
|
|
uwsgi.rpc_table = uwsgi_calloc_shared((sizeof(struct uwsgi_rpc) * uwsgi.rpc_max) * (uwsgi.numproc+1));
|
|
uwsgi.shared->rpc_count = uwsgi_calloc_shared(sizeof(uint64_t) * (uwsgi.numproc+1));
|
|
}
|