Files
uwsgi/protocol.c
T

766 lines
20 KiB
C

#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
static size_t get_content_length(char *buf, uint16_t size) {
int i;
size_t val = 0;
for(i=0;i<size;i++) {
if (buf[i] >= '0' && buf[i] <= '9') {
val = (val*10) + (buf[i] - '0');
continue;
}
break;
}
return val;
}
#ifdef UWSGI_UDP
ssize_t send_udp_message(uint8_t modifier1, char *host, char *message, uint16_t message_size) {
int fd;
struct sockaddr_in udp_addr;
char *udp_port;
ssize_t ret;
char udpbuff[1024];
if (message_size + 4 > 1024)
return -1;
udp_port = strchr(host, ':');
if (udp_port == NULL) {
return -1;
}
udp_port[0] = 0;
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
uwsgi_error("socket()");
return -1;
}
memset(&udp_addr, 0, sizeof(struct sockaddr_in));
udp_addr.sin_family = AF_INET;
udp_addr.sin_port = htons(atoi(udp_port+1));
udp_addr.sin_addr.s_addr = inet_addr(host);
udpbuff[0] = modifier1;
#ifdef __BIG_ENDIAN__
message_size = uwsgi_swap16(message_size);
#endif
memcpy(udpbuff+1, &message_size, 2);
udpbuff[3] = 0;
#ifdef __BIG_ENDIAN__
message_size = uwsgi_swap16(message_size);
#endif
memcpy(udpbuff+4, message, message_size);
ret = sendto(fd, udpbuff, message_size+4, 0, (struct sockaddr *) &udp_addr, sizeof(udp_addr));
if (ret < 0) {
uwsgi_error("sendto()");
}
close(fd);
return ret;
}
#endif
int uwsgi_enqueue_message(char *host, int port, uint8_t modifier1, uint8_t modifier2, char *message, int size, int timeout) {
struct pollfd uwsgi_poll;
struct sockaddr_in uws_addr;
int cnt;
struct uwsgi_header uh;
if (!timeout)
timeout = 1;
if (size > 0xFFFF) {
uwsgi_log( "invalid object (marshalled) size\n");
return -1;
}
uwsgi_poll.fd = socket(AF_INET, SOCK_STREAM, 0);
if (uwsgi_poll.fd < 0) {
uwsgi_error("socket()");
return -1;
}
memset(&uws_addr, 0, sizeof(struct sockaddr_in));
uws_addr.sin_family = AF_INET;
uws_addr.sin_port = htons(port);
uws_addr.sin_addr.s_addr = inet_addr(host);
uwsgi_poll.events = POLLIN;
if (timed_connect(&uwsgi_poll, (const struct sockaddr *) &uws_addr, sizeof(struct sockaddr_in), timeout, 0)) {
uwsgi_error("connect()");
close(uwsgi_poll.fd);
return -1;
}
uh.modifier1 = modifier1;
uh.pktsize = (uint16_t) size;
uh.modifier2 = modifier2;
cnt = write(uwsgi_poll.fd, &uh, 4);
if (cnt != 4) {
uwsgi_error("write()");
close(uwsgi_poll.fd);
return -1;
}
cnt = write(uwsgi_poll.fd, message, size);
if (cnt != size) {
uwsgi_error("write()");
close(uwsgi_poll.fd);
return -1;
}
return uwsgi_poll.fd;
}
ssize_t uwsgi_send_message(int fd, uint8_t modifier1, uint8_t modifier2, char *message, uint16_t size, int pfd, size_t plen, int timeout) {
struct pollfd uwsgi_mpoll;
ssize_t cnt;
struct uwsgi_header uh;
char buffer[4096];
ssize_t ret = 0;
int pret;
if (!timeout) timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
uh.modifier1 = modifier1;
uh.pktsize = size;
uh.modifier2 = modifier2;
cnt = write(fd, &uh, 4);
if (cnt != 4) {
uwsgi_error("write()");
return -1;
}
ret += cnt;
cnt = write(fd, message, size);
if (cnt != size) {
uwsgi_error("write()");
return -1;
}
ret += cnt;
// transfer data from one socket to another
if (pfd >= 0 && plen > 0) {
uwsgi_mpoll.fd = pfd;
uwsgi_mpoll.events = POLLIN;
while(plen > 0) {
pret = poll(&uwsgi_mpoll, 1, timeout*1000);
if (pret < 0) {
uwsgi_error("poll()");
return -1;
}
else if (pret == 0) {
uwsgi_log("timeout waiting for socket data\n");
return -1;
}
else {
cnt = read(pfd, buffer, UMIN(4096, plen));
if (cnt < 0) {
uwsgi_error("read()");
return -1;
}
else if (cnt == 0) {
return ret;
}
// send to peer
if (write(fd, buffer, cnt) != cnt) {
uwsgi_error("write()");
return -1;
}
ret += cnt;
plen -= cnt;
}
}
}
return ret;
}
int uwsgi_parse_response(struct pollfd *upoll, int timeout, struct uwsgi_header *uh, char *buffer) {
int rlen, i;
struct wsgi_request *wsgi_req = (struct wsgi_request *) uh;
if (!timeout)
timeout = 1;
/* first 4 byte header */
if (wsgi_req->leave_open) {
// wait for max 1 hour for the first request
uwsgi_log("ready to accept a new request on connection %d\n", wsgi_req->poll.fd);
rlen = poll(upoll, 1, 3600 * 1000);
}
else {
rlen = poll(upoll, 1, timeout * 1000);
}
if (rlen < 0) {
uwsgi_error("poll()");
exit(1);
}
else if (rlen == 0) {
uwsgi_log( "timeout. skip request\n");
close(upoll->fd);
return 0;
}
rlen = read(upoll->fd, uh, 4);
if (rlen > 0 && rlen < 4) {
i = rlen;
while (i < 4) {
rlen = poll(upoll, 1, timeout * 1000);
if (rlen < 0) {
uwsgi_error("poll()");
exit(1);
}
else if (rlen == 0) {
uwsgi_log( "timeout waiting for header. skip request.\n");
close(upoll->fd);
break;
}
rlen = read(upoll->fd, (char *) (uh) + i, 4 - i);
if (rlen <= 0) {
uwsgi_log( "broken header. skip request.\n");
close(upoll->fd);
break;
}
i += rlen;
}
if (i < 4) {
return 0;
}
}
else if (rlen <= 0) {
uwsgi_log( "invalid request header size: %d...skip\n", rlen);
close(upoll->fd);
wsgi_req->leave_open = 0;
return 0;
}
/* big endian ? */
#ifdef __BIG_ENDIAN__
uh->pktsize = uwsgi_swap16(uh->pktsize);
#endif
#ifdef UWSGI_DEBUG
uwsgi_debug("uwsgi payload size: %d (0x%X) modifier1: %d modifier2: %d\n", uh->pktsize, uh->pktsize, uh->modifier1, uh->modifier2);
#endif
/* check for max buffer size */
if (uh->pktsize > uwsgi.buffer_size) {
uwsgi_log( "invalid request block size: %d...skip\n", uh->pktsize);
close(upoll->fd);
return 0;
}
//uwsgi_log("ready for reading %d bytes\n", wsgi_req.size);
i = 0;
while (i < uh->pktsize) {
rlen = poll(upoll, 1, timeout * 1000);
if (rlen < 0) {
uwsgi_error("poll()");
exit(1);
}
else if (rlen == 0) {
uwsgi_log( "timeout. skip request. (expecting %d bytes, got %d)\n", uh->pktsize, i);
close(upoll->fd);
break;
}
rlen = read(upoll->fd, buffer + i, uh->pktsize - i);
if (rlen <= 0) {
uwsgi_log( "broken vars. skip request.\n");
close(upoll->fd);
break;
}
i += rlen;
}
if (i < uh->pktsize) {
return 0;
}
return 1;
}
int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
char *buffer = wsgi_req->buffer;
char *ptrbuf, *bufferend;
uint16_t strsize = 0;
ptrbuf = buffer;
bufferend = ptrbuf + wsgi_req->uh.pktsize;
int i, script_name= -1, path_info= -1;
/* set an HTTP 500 status as default */
wsgi_req->status = 500;
while (ptrbuf < bufferend) {
if (ptrbuf + 2 < bufferend) {
memcpy(&strsize, ptrbuf, 2);
#ifdef __BIG_ENDIAN__
strsize = uwsgi_swap16(strsize);
#endif
/* key cannot be null */
if (!strsize) {
uwsgi_log( "uwsgi key cannot be null. skip this request.\n");
return -1;
}
ptrbuf += 2;
if (ptrbuf + strsize < bufferend) {
// var key
wsgi_req->hvec[wsgi_req->var_cnt].iov_base = ptrbuf;
wsgi_req->hvec[wsgi_req->var_cnt].iov_len = strsize;
ptrbuf += strsize;
// value can be null (even at the end) so use <=
if (ptrbuf + 2 <= bufferend) {
memcpy(&strsize, ptrbuf, 2);
#ifdef __BIG_ENDIAN__
strsize = uwsgi_swap16(strsize);
#endif
ptrbuf += 2;
if (ptrbuf + strsize <= bufferend) {
//uwsgi_log("uwsgi %.*s = %.*s\n", wsgi_req->hvec[wsgi_req->var_cnt].iov_len, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, strsize, ptrbuf);
if (!uwsgi_strncmp("SCRIPT_NAME", 11, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->script_name = ptrbuf;
wsgi_req->script_name_len = strsize;
script_name = wsgi_req->var_cnt + 1;
#ifdef UWSGI_DEBUG
uwsgi_debug("SCRIPT_NAME=%.*s\n", wsgi_req->script_name_len, wsgi_req->script_name);
#endif
}
else if (!uwsgi_strncmp("PATH_INFO", 9, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->path_info = ptrbuf;
wsgi_req->path_info_len = strsize;
path_info = wsgi_req->var_cnt + 1;
#ifdef UWSGI_DEBUG
uwsgi_debug("PATH_INFO=%.*s\n", wsgi_req->path_info_len, wsgi_req->path_info);
#endif
}
else if (!uwsgi_strncmp("SERVER_PROTOCOL", 15, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->protocol = ptrbuf;
wsgi_req->protocol_len = strsize;
}
else if (!uwsgi_strncmp("REQUEST_URI", 11, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->uri = ptrbuf;
wsgi_req->uri_len = strsize;
}
else if (!uwsgi_strncmp("QUERY_STRING", 12, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->query_string = ptrbuf;
wsgi_req->query_string_len = strsize;
}
else if (!uwsgi_strncmp("REQUEST_METHOD", 14, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->method = ptrbuf;
wsgi_req->method_len = strsize;
}
else if (!uwsgi_strncmp("REMOTE_ADDR", 11, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->remote_addr = ptrbuf;
wsgi_req->remote_addr_len = strsize;
}
else if (!uwsgi_strncmp("REMOTE_USER", 11, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->remote_user = ptrbuf;
wsgi_req->remote_user_len = strsize;
}
else if (!uwsgi_strncmp("UWSGI_SCHEME", 12, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->scheme = ptrbuf;
wsgi_req->scheme_len = strsize;
}
else if (!uwsgi_strncmp("UWSGI_SCRIPT", 12, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len )) {
wsgi_req->script = ptrbuf;
wsgi_req->script_len = strsize;
}
else if (!uwsgi_strncmp("UWSGI_MODULE", 12, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->module = ptrbuf;
wsgi_req->module_len = strsize;
}
else if (!uwsgi_strncmp("UWSGI_CALLABLE", 14, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->callable = ptrbuf;
wsgi_req->callable_len = strsize;
}
else if (!uwsgi_strncmp("UWSGI_PYHOME", 12, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->pyhome = ptrbuf;
wsgi_req->pyhome_len = strsize;
}
else if (!uwsgi_strncmp("UWSGI_CHDIR", 11, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->chdir = ptrbuf;
wsgi_req->chdir_len = strsize;
}
else if (!uwsgi_strncmp("SERVER_NAME", 11, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len) && !uwsgi.vhost_host) {
wsgi_req->host = ptrbuf;
wsgi_req->host_len = strsize;
#ifdef UWSGI_DEBUG
uwsgi_debug("SERVER_NAME=%.*s\n", wsgi_req->host_len, wsgi_req->host);
#endif
}
else if (!uwsgi_strncmp("HTTP_HOST", 9, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len) && uwsgi.vhost_host) {
wsgi_req->host = ptrbuf;
wsgi_req->host_len = strsize;
#ifdef UWSGI_DEBUG
uwsgi_debug("HTTP_HOST=%.*s\n", wsgi_req->host_len, wsgi_req->host);
#endif
}
else if (!uwsgi_strncmp("HTTPS", 5, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->https = ptrbuf;
wsgi_req->https_len = strsize;
}
else if (!uwsgi_strncmp("CONTENT_LENGTH", 14, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->post_cl = get_content_length(ptrbuf, strsize);
}
if (wsgi_req->var_cnt < uwsgi.vec_size - (4 + 1)) {
wsgi_req->var_cnt++;
}
else {
uwsgi_log( "max vec size reached. skip this header.\n");
return -1;
}
// var value
wsgi_req->hvec[wsgi_req->var_cnt].iov_base = ptrbuf;
wsgi_req->hvec[wsgi_req->var_cnt].iov_len = strsize;
//uwsgi_log("%.*s = %.*s\n", wsgi_req->hvec[wsgi_req->var_cnt-1].iov_len, wsgi_req->hvec[wsgi_req->var_cnt-1].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len, wsgi_req->hvec[wsgi_req->var_cnt].iov_base);
if (wsgi_req->var_cnt < uwsgi.vec_size - (4 + 1)) {
wsgi_req->var_cnt++;
}
else {
uwsgi_log( "max vec size reached. skip this header.\n");
return -1;
}
ptrbuf += strsize;
}
else {
return -1;
}
}
else {
return -1;
}
}
}
else {
return -1;
}
}
if (uwsgi.manage_script_name) {
if (uwsgi.apps_cnt > 0 && wsgi_req->path_info_len > 1) {
// starts with 1 as the 0 app is the default (/) one
int best_found = 0;
char *orig_path_info = wsgi_req->path_info;
int orig_path_info_len = wsgi_req->path_info_len;
// if SCRIPT_NAME is not allocated, add a slot for it
if (script_name == -1) {
if (wsgi_req->var_cnt >= uwsgi.vec_size - (4 + 2)) {
uwsgi_log( "max vec size reached. skip this header.\n");
return -1;
}
wsgi_req->var_cnt++;
wsgi_req->hvec[wsgi_req->var_cnt].iov_base = "SCRIPT_NAME";
wsgi_req->hvec[wsgi_req->var_cnt].iov_len = 11;
wsgi_req->var_cnt++;
script_name = wsgi_req->var_cnt;
}
for(i=1;i<uwsgi.apps_cnt;i++) {
uwsgi_log("app mountpoint = %.*s\n", uwsgi.apps[i].mountpoint_len, uwsgi.apps[i].mountpoint);
if (orig_path_info_len >= uwsgi.apps[i].mountpoint_len) {
if (!uwsgi_startswith(orig_path_info, uwsgi.apps[i].mountpoint, uwsgi.apps[i].mountpoint_len) && uwsgi.apps[i].mountpoint_len > best_found) {
best_found = uwsgi.apps[i].mountpoint_len;
wsgi_req->script_name = uwsgi.apps[i].mountpoint;
wsgi_req->script_name_len = uwsgi.apps[i].mountpoint_len;
wsgi_req->path_info = orig_path_info+wsgi_req->script_name_len;
wsgi_req->path_info_len = orig_path_info_len-wsgi_req->script_name_len;
wsgi_req->hvec[script_name].iov_base = wsgi_req->script_name;
wsgi_req->hvec[script_name].iov_len = wsgi_req->script_name_len;
wsgi_req->hvec[path_info].iov_base = wsgi_req->path_info;
wsgi_req->hvec[path_info].iov_len = wsgi_req->path_info_len;
uwsgi_log("managed SCRIPT_NAME = %.*s PATH_INFO = %.*s\n", wsgi_req->script_name_len, wsgi_req->script_name, wsgi_req->path_info_len, wsgi_req->path_info);
}
}
}
}
}
return 0;
}
int uwsgi_ping_node(int node, struct wsgi_request *wsgi_req) {
struct pollfd uwsgi_poll;
struct uwsgi_cluster_node *ucn = &uwsgi.shared->nodes[node];
if (ucn->name[0] == 0) {
return 0;
}
if (ucn->status == UWSGI_NODE_OK) {
return 0;
}
uwsgi_poll.fd = socket(AF_INET, SOCK_STREAM, 0);
if (uwsgi_poll.fd < 0) {
uwsgi_error("socket()");
return -1;
}
if (timed_connect(&uwsgi_poll, (const struct sockaddr *) &ucn->ucn_addr, sizeof(struct sockaddr_in), uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0)) {
close(uwsgi_poll.fd);
return -1;
}
wsgi_req->uh.modifier1 = UWSGI_MODIFIER_PING;
wsgi_req->uh.pktsize = 0;
wsgi_req->uh.modifier2 = 0;
if (write(uwsgi_poll.fd, wsgi_req, 4) != 4) {
uwsgi_error("write()");
return -1;
}
uwsgi_poll.events = POLLIN;
if (!uwsgi_parse_response(&uwsgi_poll, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], (struct uwsgi_header *) wsgi_req, wsgi_req->buffer)) {
return -1;
}
return 0;
}
ssize_t uwsgi_send_empty_pkt(int fd, char *socket_name, uint8_t modifier1, uint8_t modifier2) {
struct uwsgi_header uh;
char *port;
uint16_t s_port;
struct sockaddr_in uaddr;
int ret;
uh.modifier1 = modifier1;
uh.pktsize = 0;
uh.modifier2 = modifier2;
if (socket_name) {
port = strchr(socket_name, ':');
if (!port) return -1;
s_port = atoi(port+1);
port[0] = 0;
memset(&uaddr, 0, sizeof(struct sockaddr_in));
uaddr.sin_family = AF_INET;
uaddr.sin_addr.s_addr = inet_addr(socket_name);
uaddr.sin_port = htons(s_port);
port[0] = ':';
ret = sendto(fd, &uh, 4, 0, (struct sockaddr *) &uaddr, sizeof(struct sockaddr_in));
}
else {
ret = send(fd, &uh, 4, 0);
}
if (ret < 0) {
uwsgi_error("sendto()");
}
return ret;
}
int uwsgi_get_dgram(int fd, struct wsgi_request *wsgi_req) {
ssize_t rlen;
struct uwsgi_header *uh;
static char *buffer = NULL;
struct sockaddr_in sin;
socklen_t sin_len = sizeof(struct sockaddr_in);
if (!buffer) {
buffer = uwsgi_malloc(uwsgi.buffer_size + 4);
}
rlen = recvfrom(fd, buffer, uwsgi.buffer_size + 4, 0, (struct sockaddr *) &sin, &sin_len);
if (rlen < 0) {
uwsgi_error("recvfrom");
return -1;
}
uwsgi_log("recevied request from %s\n", inet_ntoa(sin.sin_addr));
if (rlen < 4) {
uwsgi_log("invalid uwsgi packet\n");
return -1;
}
uh = (struct uwsgi_header *) buffer;
wsgi_req->uh.modifier1 = uh->modifier1;
/* big endian ? */
#ifdef __BIG_ENDIAN__
uh->pktsize = uwsgi_swap16(uh->pktsize);
#endif
wsgi_req->uh.pktsize = uh->pktsize;
wsgi_req->uh.modifier2 = uh->modifier2;
if (wsgi_req->uh.pktsize > uwsgi.buffer_size) {
uwsgi_log("invalid uwsgi packet size, probably you need to increase buffer size\n");
return -1;
}
wsgi_req->buffer = buffer+4;
uwsgi_log("request received %d %d\n", wsgi_req->uh.modifier1, wsgi_req->uh.modifier2);
return 0;
}
int uwsgi_hooked_parse(char *buffer, size_t len, void (*hook)(char *, uint16_t, char *, uint16_t, void*), void *data) {
char *ptrbuf, *bufferend;
uint16_t keysize = 0, valsize = 0;
char *key;
ptrbuf = buffer;
bufferend = buffer + len;
while (ptrbuf < bufferend) {
if (ptrbuf + 2 >= bufferend) return -1;
memcpy(&keysize, ptrbuf, 2);
#ifdef __BIG_ENDIAN__
keysize = uwsgi_swap16(keysize);
#endif
/* key cannot be null */
if (!keysize) return -1;
ptrbuf += 2;
if (ptrbuf + keysize > bufferend) return -1;
// key
key = ptrbuf;
ptrbuf += keysize;
// value can be null
if (ptrbuf + 2 > bufferend) return -1;
memcpy(&valsize, ptrbuf, 2);
#ifdef __BIG_ENDIAN__
valsize = uwsgi_swap16(valsize);
#endif
ptrbuf += 2;
if (ptrbuf + valsize > bufferend) return -1;
// now call the hook
hook(key, keysize, ptrbuf, valsize, data);
ptrbuf += valsize;
}
return 0;
}
int uwsgi_hooked_parse_dict_dgram(int fd, char *buffer, size_t len, uint8_t modifier1, uint8_t modifier2, void (*hook)(char *, uint16_t, char *, uint16_t, void *), void *data) {
struct uwsgi_header *uh;
ssize_t rlen;
struct sockaddr_in sin;
socklen_t sin_len = sizeof(struct sockaddr_in);
char *ptrbuf, *bufferend;
rlen = recvfrom(fd, buffer, len, 0, (struct sockaddr *) &sin, &sin_len);
if (rlen < 0) {
uwsgi_error("recvfrom()");
return -1;
}
uwsgi_log("recevied request from %s\n", inet_ntoa(sin.sin_addr));
uwsgi_log("RLEN: %d\n", rlen);
// check for valid dict 4(header) 2(non-zero key)+1 2(value)
if (rlen < (4+2+1+2)) {
uwsgi_log("invalid uwsgi dictionary\n");
return -1;
}
uh = (struct uwsgi_header *) buffer;
if (uh->modifier1 != modifier1 || uh->modifier2 != modifier2) {
uwsgi_log("invalid uwsgi dictionary received, modifier1: %d modifier2: %d\n", uh->modifier1, uh->modifier2);
return -1;
}
ptrbuf = buffer + 4;
/* big endian ? */
#ifdef __BIG_ENDIAN__
uh->pktsize = uwsgi_swap16(uh->pktsize);
#endif
if (uh->pktsize > len) {
uwsgi_log("* WARNING * the uwsgi dictionary received is too big, data will be truncated\n");
bufferend = ptrbuf + len;
}
else {
bufferend = ptrbuf + uh->pktsize;
}
uwsgi_log("%p %p %d\n", ptrbuf, bufferend, bufferend-ptrbuf);
uwsgi_hooked_parse(ptrbuf, bufferend-ptrbuf, hook, data);
return 0;
}
int uwsgi_string_sendto(int fd, uint8_t modifier1, uint8_t modifier2, struct sockaddr *sa, socklen_t sa_len, char *message, size_t len) {
ssize_t rlen ;
struct uwsgi_header *uh;
char *upkt = uwsgi_malloc(len + 4);
uh = (struct uwsgi_header *) upkt;
uh->modifier1 = modifier1;
uh->pktsize = len;
uh->modifier2 = modifier2;
memcpy(upkt+4, message, len);
rlen = sendto(fd, upkt, len+4, 0, sa, sa_len);
if (rlen < 0) {
uwsgi_error("sendto()");
}
free(upkt);
return rlen;
}