Пример #1
0
Файл: cache.c Проект: Algy/uwsgi
static void cache_simple_command(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {

        struct wsgi_request *wsgi_req = (struct wsgi_request *) data;

        if (vallen > 0) {
                if (!uwsgi_strncmp(key, keylen, "key", 3)) {
        		uint64_t vallen = 0;
                        char *value = uwsgi_cache_magic_get(val, vallen, &vallen, NULL, NULL);
                        if (value) {
				uwsgi_response_write_body_do(wsgi_req, value, vallen);
				free(value);
                        }

                }
                else if (!uwsgi_strncmp(key, keylen, "get", 3)) {
        		uint64_t vallen = 0;
                        char *value = uwsgi_cache_magic_get(val, vallen, &vallen, NULL, NULL);
                        if (value) {
				uwsgi_response_write_body_do(wsgi_req, value, vallen);
				free(value);
                        }
                        else {
				uwsgi_404(wsgi_req);
                        }
                }
        }
}
Пример #2
0
void fr_get_hostname(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {

	struct corerouter_peer *peer = (struct corerouter_peer *) data;
	struct fastrouter_session *fr = (struct fastrouter_session *) peer->session;

	//uwsgi_log("%.*s = %.*s\n", keylen, key, vallen, val);
	if (!uwsgi_strncmp("SERVER_NAME", 11, key, keylen) && !peer->key_len) {
		peer->key = val;
		peer->key_len = vallen;
		return;
	}

	if (!uwsgi_strncmp("HTTP_HOST", 9, key, keylen) && !fr->has_key) {
		peer->key = val;
		peer->key_len = vallen;
		return;
	}

	if (!uwsgi_strncmp("UWSGI_FASTROUTER_KEY", 20, key, keylen)) {
		fr->has_key = 1;
		peer->key = val;
		peer->key_len = vallen;
		return;
	}
}
Пример #3
0
void cache_command(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {

        struct wsgi_request *wsgi_req = (struct wsgi_request *) data;
        uint64_t tmp_vallen = 0;

        if (vallen > 0) {
                if (!uwsgi_strncmp(key, keylen, "key", 3)) {
                        val = uwsgi_cache_get(val, vallen, &tmp_vallen);
                        if (val && tmp_vallen > 0) {
#ifdef UWSGI_DEBUG
				uwsgi_log("cache value size: %llu\n", tmp_vallen);
#endif
                                wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, val, tmp_vallen);
                        }

                }
                else if (!uwsgi_strncmp(key, keylen, "get", 3)) {
                        val = uwsgi_cache_get(val, vallen, &tmp_vallen);
                        if (val && vallen > 0) {
                                wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, val, tmp_vallen);
                        }
                        else {
                                wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.0 404 Not Found\r\n\r\n<h1>Not Found</h1>", 44);
                        }
                }
        }
}
Пример #4
0
int uwsgi_add_expires_type(struct wsgi_request *wsgi_req, char *mime_type, int mime_type_len, struct stat *st) {

	struct uwsgi_dyn_dict *udd = uwsgi.static_expires_type;
	time_t now = wsgi_req->start_of_request / 1000000;
	// 30+1
	char expires[31];

	while (udd) {
		if (!uwsgi_strncmp(udd->key, udd->keylen, mime_type, mime_type_len)) {
			int delta = uwsgi_str_num(udd->value, udd->vallen);
			int size = set_http_date(now + delta, expires);
			if (size > 0) {
				if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
			}
			return 0;
		}
		udd = udd->next;
	}

	udd = uwsgi.static_expires_type_mtime;
	while (udd) {
		if (!uwsgi_strncmp(udd->key, udd->keylen, mime_type, mime_type_len)) {
			int delta = uwsgi_str_num(udd->value, udd->vallen);
			int size = set_http_date(st->st_mtime + delta, expires);
			if (size > 0) {
				if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
			}
			return 0;
		}
		udd = udd->next;
	}

	return 0;
}
Пример #5
0
void corerouter_manage_subscription(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {

	struct uwsgi_subscribe_req *usr = (struct uwsgi_subscribe_req *) data;

	if (!uwsgi_strncmp("key", 3, key, keylen)) {
		usr->key = val;
		usr->keylen = vallen;
	}
	else if (!uwsgi_strncmp("address", 7, key, keylen)) {
		usr->address = val;
		usr->address_len = vallen;
	}
	else if (!uwsgi_strncmp("modifier1", 9, key, keylen)) {
		usr->modifier1 = uwsgi_str_num(val, vallen);
	}
	else if (!uwsgi_strncmp("cores", 5, key, keylen)) {
		usr->cores = uwsgi_str_num(val, vallen);
	}
	else if (!uwsgi_strncmp("load", 4, key, keylen)) {
		usr->load = uwsgi_str_num(val, vallen);
	}
	else if (!uwsgi_strncmp("weight", 6, key, keylen)) {
		usr->weight = uwsgi_str_num(val, vallen);
	}
	else if (!uwsgi_strncmp("unix", 4, key, keylen)) {
		usr->unix_check = uwsgi_str_num(val, vallen);
	}
	else if (!uwsgi_strncmp("sign", 4, key, keylen)) {
		usr->sign = val;
                usr->sign_len = vallen;
	}
}
Пример #6
0
static int uwsgi_routing_func_basicauth(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {

	// skip if already authenticated
	if (wsgi_req->remote_user_len > 0) {
		return UWSGI_ROUTE_NEXT;
	}


	if (wsgi_req->authorization_len > 7 && ur->data2_len > 0) {
		if (strncmp(wsgi_req->authorization, "Basic ", 6))
			goto forbidden;

		size_t auth_len = 0;
		char *auth = uwsgi_base64_decode(wsgi_req->authorization+6, wsgi_req->authorization_len-6, &auth_len);
		if (auth) {
			if (!ur->custom) {
				// check htpasswd-like file
				uint16_t ulen = htpasswd_check(ur->data2, auth);
				if (ulen > 0) {
					wsgi_req->remote_user = uwsgi_req_append(wsgi_req, "REMOTE_USER", 11, auth, ulen); 
					if (!wsgi_req->remote_user) {
						free(auth);
						goto forbidden;
					}
					wsgi_req->remote_user_len = ulen;
				}
				else if (ur->data3_len == 0) {
					free(auth);
					goto forbidden;
				}
			}
			else {
				if (!uwsgi_strncmp(auth, auth_len, ur->data2, ur->data2_len)) {
					wsgi_req->remote_user = uwsgi_req_append(wsgi_req, "REMOTE_USER", 11, auth, ur->custom); 
					if (!wsgi_req->remote_user) {
						free(auth);
						goto forbidden;
					}
					wsgi_req->remote_user_len = ur->custom;
				}
				else if (ur->data3_len == 0) {
					free(auth);
					goto forbidden;
				}
			}
			free(auth);
			return UWSGI_ROUTE_NEXT;
		}
	}

forbidden:
	if (uwsgi_response_prepare_headers(wsgi_req, "401 Authorization Required", 26)) goto end;
	char *realm = uwsgi_concat3n("Basic realm=\"", 13, ur->data, ur->data_len, "\"", 1);
	// no need to check for errors
	uwsgi_response_add_header(wsgi_req, "WWW-Authenticate", 16, realm, 13 + ur->data_len + 1);
	free(realm);
	uwsgi_response_write_body_do(wsgi_req, "Unauthorized", 12);
end:
	return UWSGI_ROUTE_BREAK;
}
Пример #7
0
void fastrouter_manage_subscription(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
	
	struct uwsgi_subscribe_req *usr = (struct uwsgi_subscribe_req *) data;
	
	if (!uwsgi_strncmp("key", 3, key, keylen)) {
		usr->key = val;
		usr->keylen = vallen;
	}
	else if (!uwsgi_strncmp("address", 7, key, keylen)) {
		usr->address = val;
		usr->address_len = vallen;
	}

	else if (!uwsgi_strncmp("modifier1", 9, key, keylen)) {
		usr->modifier1 = uwsgi_str_num(val, vallen);
	}
}
Пример #8
0
static void fr_get_hostname(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {

	struct corerouter_peer *peer = (struct corerouter_peer *) data;
	struct fastrouter_session *fr = (struct fastrouter_session *) peer->session;

	//uwsgi_log("%.*s = %.*s\n", keylen, key, vallen, val);
	if (!uwsgi_strncmp("SERVER_NAME", 11, key, keylen) && !peer->key_len) {
		if (vallen <= 0xff) {
			memcpy(peer->key, val, vallen);
			peer->key_len = vallen;
		}
		return;
	}

	if (!uwsgi_strncmp("HTTP_HOST", 9, key, keylen) && !fr->has_key) {
		if (vallen <= 0xff) {
                        memcpy(peer->key, val, vallen);
                        peer->key_len = vallen;
                }
		return;
	}

	if (!uwsgi_strncmp("UWSGI_FASTROUTER_KEY", 20, key, keylen)) {
		if (vallen <= 0xff) {
			fr->has_key = 1;
                        memcpy(peer->key, val, vallen);
                        peer->key_len = vallen;
		}
		return;
	}

	if (!uwsgi_strncmp("REMOTE_ADDR", 11, key, keylen)) {
		if (vallen < sizeof(peer->session->client_address)) {
			strncpy(peer->session->client_address, val, vallen);
		}
                return;
        }

	if (!uwsgi_strncmp("REMOTE_PORT", 11, key, keylen)) {
		if (vallen < sizeof(peer->session->client_port)) {
			strncpy(peer->session->client_port, val, vallen);
		}
                return;
        }
}
Пример #9
0
struct uwsgi_subscribe_slot *uwsgi_get_subscribe_slot(struct uwsgi_subscribe_slot **slot, char *key, uint16_t keylen) {

	if (keylen > 0xff)
		return NULL;

	uint32_t hash = djb33x_hash(key, keylen);
	int hash_key = hash % 0xffff;

	struct uwsgi_subscribe_slot *current_slot = slot[hash_key];


#ifdef UWSGI_DEBUG
	uwsgi_log("****************************\n");
	while (current_slot) {
		uwsgi_log("slot %.*s %d\n", current_slot->keylen, current_slot->key, current_slot->hits);
		current_slot = current_slot->next;
	}
	uwsgi_log("****************************\n");
	current_slot = slot[hash_key];
#endif

	while (current_slot) {
		if (!uwsgi_strncmp(key, keylen, current_slot->key, current_slot->keylen)) {
			// auto optimization
			if (current_slot->prev) {
				if (current_slot->hits > current_slot->prev->hits) {
					struct uwsgi_subscribe_slot *slot_parent = current_slot->prev->prev, *slot_prev = current_slot->prev;
					if (slot_parent) {
						slot_parent->next = current_slot;
					}
					else {
						slot[hash_key] = current_slot;
					}

					if (current_slot->next) {
						current_slot->next->prev = slot_prev;
					}

					slot_prev->prev = current_slot;
					slot_prev->next = current_slot->next;

					current_slot->next = slot_prev;
					current_slot->prev = slot_parent;

				}
			}
			return current_slot;
		}
		current_slot = current_slot->next;
		// check for loopy optimization
		if (current_slot == slot[hash_key])
			break;
	}

	return NULL;
}
Пример #10
0
Файл: ssi.c Проект: Algy/uwsgi
static struct uwsgi_ssi_cmd* uwsgi_ssi_get_cmd(char *name, size_t name_len) {
	struct uwsgi_ssi_cmd *usc = uwsgi_ssi_commands;
	while(usc) {
		if (!uwsgi_strncmp(usc->name, usc->name_len, name, name_len)) {
			return usc;
		}
		usc = usc->next;
	}
	return NULL;
}
Пример #11
0
// check if a log should raise an alarm
void uwsgi_alarm_log_check(char *msg, size_t len) {
	if (!uwsgi_strncmp(msg, len, "[uwsgi-alarm", 12)) return;
	struct uwsgi_alarm_log *ual = uwsgi.alarm_logs;
        while(ual) {
        	if (uwsgi_regexp_match(ual->pattern, ual->pattern_extra, msg, len) >= 0) {
                	uwsgi_alarm_log_run(ual, msg, len);
                }
                ual = ual->next;
	}
}
Пример #12
0
struct uwsgi_logvar *uwsgi_logvar_get(struct wsgi_request *wsgi_req, char *key, uint8_t keylen) {
	struct uwsgi_logvar *lv = wsgi_req->logvars;
	while(lv) {
		if (!uwsgi_strncmp(key, keylen, lv->key, lv->keylen)) {
			return lv;
		}
		lv = lv->next;
	}
	return NULL;
}
Пример #13
0
// call the alarm func
void uwsgi_alarm_run(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
	time_t now = uwsgi_now();
	// avoid alarm storming/loop if last message is the same
	if (!uwsgi_strncmp(msg, len, uai->last_msg, uai->last_msg_size)) {	
		if (now - uai->last_run < uwsgi.alarm_freq) return;
	}
	uai->alarm->func(uai, msg, len);
	uai->last_run = uwsgi_now();
	memcpy(uai->last_msg, msg, len);
	uai->last_msg_size = len;
}
Пример #14
0
Файл: ssi.c Проект: Algy/uwsgi
static char *uwsgi_ssi_get_arg(struct uwsgi_ssi_arg *argv, int argc, char *key, size_t key_len, size_t *val_len) {
	int i;
	for(i=0;i<argc;i++) {
		struct uwsgi_ssi_arg *arg = &argv[i];
		if (!uwsgi_strncmp(arg->key, arg->key_len, key, key_len)) {
			*val_len = arg->val_len;	
			return arg->value;
		}
	}

	return NULL;
}
Пример #15
0
char *uwsgi_get_mime_type(char *name, int namelen, size_t *size) {

	int i;
	int count = 0;
	char *ext = NULL;
	for (i = namelen - 1; i >= 0; i--) {
		if (!isalnum((int) name[i])) {
			if (name[i] == '.') {
				ext = name + (namelen - count);
				break;
			}
		}
		count++;
	}

	if (!ext)
		return NULL;

	struct uwsgi_dyn_dict *udd = uwsgi.mimetypes;
	while (udd) {
		if (!uwsgi_strncmp(ext, count, udd->key, udd->keylen)) {
			udd->hits++;
			// auto optimization
			if (udd->prev) {
				if (udd->hits > udd->prev->hits) {
					struct uwsgi_dyn_dict *udd_parent = udd->prev->prev, *udd_prev = udd->prev;
					if (udd_parent) {
						udd_parent->next = udd;
					}

					if (udd->next) {
						udd->next->prev = udd_prev;
					}

					udd_prev->prev = udd;
					udd_prev->next = udd->next;

					udd->prev = udd_parent;
					udd->next = udd_prev;

					if (udd->prev == NULL) {
						uwsgi.mimetypes = udd;
					}
				}
			}
			*size = udd->vallen;
			return udd->value;
		}
		udd = udd->next;
	}

	return NULL;
}
Пример #16
0
static int uwsgi_sni_cb(SSL *ssl, int *ad, void *arg) {
        const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
        if (!servername) return SSL_TLSEXT_ERR_NOACK;
        size_t servername_len = strlen(servername);

        struct uwsgi_string_list *usl = uwsgi.sni;
        while(usl) {
                if (!uwsgi_strncmp(usl->value, usl->len, (char *)servername, servername_len)) {
                        SSL_set_SSL_CTX(ssl, usl->custom_ptr);
                        return SSL_TLSEXT_ERR_OK;
                }
                usl = usl->next;
        }

#ifdef UWSGI_PCRE
        struct uwsgi_regexp_list *url = uwsgi.sni_regexp;
        while(url) {
                if (uwsgi_regexp_match(url->pattern, url->pattern_extra, (char *)servername, servername_len) >= 0) {
                        SSL_set_SSL_CTX(ssl, url->custom_ptr);
                        return SSL_TLSEXT_ERR_OK;
                }
                url = url->next;
        }
#endif

	if (uwsgi.sni_dir) {
		size_t sni_dir_len = strlen(uwsgi.sni_dir);
		char *sni_dir_cert = uwsgi_concat4n(uwsgi.sni_dir, sni_dir_len, "/", 1, (char *) servername, servername_len, ".crt", 4);
		char *sni_dir_key = uwsgi_concat4n(uwsgi.sni_dir, sni_dir_len, "/", 1, (char *) servername, servername_len, ".key", 4);
		char *sni_dir_client_ca = uwsgi_concat4n(uwsgi.sni_dir, sni_dir_len, "/", 1, (char *) servername, servername_len, ".ca", 3);
		if (uwsgi_file_exists(sni_dir_cert) && uwsgi_file_exists(sni_dir_key)) {
			char *client_ca = NULL;
			if (uwsgi_file_exists(sni_dir_client_ca)) {
				client_ca = sni_dir_client_ca;
			}
			usl = uwsgi_ssl_add_sni_item(uwsgi_str((char *)servername), sni_dir_cert, sni_dir_key, uwsgi.sni_dir_ciphers, client_ca);
			if (!usl) goto done;
			free(sni_dir_cert);
			free(sni_dir_key);
			free(sni_dir_client_ca);
			SSL_set_SSL_CTX(ssl, usl->custom_ptr);
			uwsgi_log("[uwsgi-sni for pid %d] added context for %s\n", (int) getpid(), servername);
			return SSL_TLSEXT_ERR_OK;
		}
done:
		free(sni_dir_cert);
		free(sni_dir_key);
		free(sni_dir_client_ca);
	}

        return SSL_TLSEXT_ERR_NOACK;
}
Пример #17
0
int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t filename_len, struct stat *st) {
	// check for filename size
	if (filename_len + 4 > PATH_MAX) return 0;
	// check for supported encodings
	if (!uwsgi_contains_n(wsgi_req->encoding, wsgi_req->encoding_len, "gzip", 4) ) return 0;

	// check for 'all'
	if (uwsgi.static_gzip_all) goto gzip;

	// check for dirs/prefix
	struct uwsgi_string_list *usl = uwsgi.static_gzip_dir;
	while(usl) {
		if (!uwsgi_starts_with(filename, filename_len, usl->value, usl->len)) {
			goto gzip;
		}
		usl = usl->next;
	} 

	// check for ext/suffix
	usl = uwsgi.static_gzip_ext;
        while(usl) {
		if (!uwsgi_strncmp(filename + (filename_len - usl->len), usl->len, usl->value, usl->len)) {
			goto gzip;
		}
                usl = usl->next;
        }

#ifdef UWSGI_PCRE
	// check for regexp
	struct uwsgi_regexp_list *url = uwsgi.static_gzip;
	while(url) {
		if (uwsgi_regexp_match(url->pattern, url->pattern_extra, filename, filename_len) >= 0) {
			goto gzip;
		}
		url = url->next;
	}
#endif
	return 0;

gzip:

	memcpy(filename + filename_len, ".gz\0", 4);
	filename_len += 3;
	
	if (stat(filename, st)) {
		filename_len -= 3;
		filename[filename_len] = 0;
		return 0;
	}
	
	return 1;
}
Пример #18
0
struct uwsgi_spooler *uwsgi_get_spooler_by_name(char *name, size_t name_len) {

	struct uwsgi_spooler *uspool = uwsgi.spoolers;

	while (uspool) {
		if (!uwsgi_strncmp(uspool->dir, strlen(uspool->dir), name, name_len)) {
			return uspool;
		}
		uspool = uspool->next;
	}

	return NULL;
}
Пример #19
0
static void spooler_req_parser_hook(char *key, uint16_t key_len, char *value, uint16_t value_len, void *data) {
	struct spooler_req *sr = (struct spooler_req *) data;
	if (!uwsgi_strncmp(key, key_len, "spooler", 7)) {
		sr->spooler = value;
		sr->spooler_len = value_len;
		return;
	} 

	if (!uwsgi_strncmp(key, key_len, "priority", 8)) {
                sr->priority = value;
                sr->priority_len = value_len;
                return;
        }

	if (!uwsgi_strncmp(key, key_len, "at", 2)) {
		// at can be a float...
		char *dot = memchr(value, '.', value_len);
		if (dot) {
			value_len = dot - value;
		}
		sr->at = uwsgi_str_num(value, value_len);
		return;
	}
}
Пример #20
0
static char *check_qs(char *qs, uint16_t qs_len, char *key, uint16_t keylen, uint16_t *vallen) {
	// search for the equal sign
	char *equal = memchr(qs, '=', qs_len);
	if (!equal) return NULL;
	
	if (uwsgi_strncmp(key, keylen, qs, equal-qs)) {
		return NULL;
	}

	qs_len -= (equal-qs)+1;
	if (qs_len == 0) return NULL;

	*vallen = qs_len;
	return equal+1;
}
Пример #21
0
struct uwsgi_subscribe_node *uwsgi_get_subscribe_node_by_name(struct uwsgi_subscribe_slot **slot, char *key, uint16_t keylen, char *val, uint16_t vallen) {

	if (keylen > 0xff)
		return NULL;
	struct uwsgi_subscribe_slot *current_slot = uwsgi_get_subscribe_slot(slot, key, keylen);
	if (current_slot) {
		struct uwsgi_subscribe_node *node = current_slot->nodes;
		while (node) {
			if (!uwsgi_strncmp(val, vallen, node->name, node->len)) {
				return node;
			}
			node = node->next;
		}
	}

	return NULL;
}
Пример #22
0
static uint16_t htpasswd_check(char *filename, char *auth) {

	char line[1024];

	char *colon = strchr(auth, ':');
	if (!colon) return 0;

	FILE *htpasswd = fopen(filename, "r");
	if (!htpasswd) {
		return 0;
	}
	while(fgets(line, 1024, htpasswd)) {
		char *colon2 = strchr(line, ':');
		if (!colon2) break;	

		char *cpwd = colon2+1;
		size_t clen = strlen(cpwd);
		if (clen < 13) break;

		if (clen > 13) cpwd[13] = 0;

#ifdef __linux__
		struct crypt_data cd;
		cd.initialized = 0;
		// we do as nginx here
		cd.current_salt[0] = ~cpwd[0];
		char *crypted = crypt_r( colon+1, cpwd, &cd);
#else
		if (uwsgi.threads > 1) pthread_mutex_lock(&ur_basicauth_crypt_mutex);
		char *crypted = crypt( colon+1, cpwd);
		if (uwsgi.threads > 1) pthread_mutex_unlock(&ur_basicauth_crypt_mutex);
#endif
		if (!crypted) continue;

		if (!strcmp( crypted, cpwd )) {
			if (!uwsgi_strncmp(auth, colon-auth, line, colon2-line)) {
				fclose(htpasswd);
				return colon-auth;
			}
		}
	}
	
	fclose(htpasswd);

	return 0;
}
Пример #23
0
static char *uwsgi_cgi_get_helper(char *filename) {

	struct uwsgi_dyn_dict *helpers = uc.helpers;
	size_t len = strlen(filename);

	while(helpers) {
		if (len >= (size_t) helpers->keylen) {
			if (!uwsgi_strncmp((filename+len)-helpers->keylen, helpers->keylen, helpers->key, helpers->keylen)) {
				return helpers->value;
			}
		}
		helpers = helpers->next;
	}

	return NULL;
	
}
Пример #24
0
static char *check_cookie(char *cookie, uint16_t cookie_len, char *key, uint16_t keylen, uint16_t *vallen) {
	uint16_t orig_cookie_len = cookie_len-1;
	// first lstrip white spaces
	char *ptr = cookie;
	uint16_t i;
	for(i=0;i<cookie_len;i++) {
		if (isspace((int)ptr[i])) {
			cookie++;
			cookie_len--;
		}
		else {
			break;
		}
	}

	// then rstrip (skipping the first char...)
	for(i=orig_cookie_len;i>0;i--) {
		if (isspace((int)ptr[i])) {
			cookie_len--;
		}
		else {
			break;
		}
	}

	// now search for the first equal sign
	char *equal = memchr(cookie, '=', cookie_len);
	if (!equal) return NULL;
	
	if (uwsgi_strncmp(key, keylen, cookie, equal-cookie)) {
		return NULL;
	}

	cookie_len -= (equal-cookie)+1;
	if (cookie_len == 0) return NULL;

	*vallen = cookie_len;
	return equal+1;
}
Пример #25
0
void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {

        struct uwsgi_logchunk *logchunk = uwsgi.logchunks;

        if (logchunk) {
                while(logchunk) {
                        if (!logchunk->next) {
                                logchunk->next = uwsgi_calloc(sizeof(struct uwsgi_logchunk));
                                logchunk = logchunk->next;
                                break;
                        }
                        logchunk = logchunk->next;
                }
        }
        else {
                uwsgi.logchunks = uwsgi_calloc(sizeof(struct uwsgi_logchunk));
                logchunk = uwsgi.logchunks;
        }

        /*
                0 -> raw test
                1 -> offsetof variable
                2 -> logvar
                3 -> func
        */

        logchunk->type = variable;
        logchunk->vec = pos;
        // normal text
        logchunk->ptr = ptr;
        logchunk->len = len;
        // variable
        if (variable) {
                if (!uwsgi_strncmp(ptr, len, "uri", 3)) {
                        logchunk->pos = offsetof(struct wsgi_request, uri);
                        logchunk->pos_len = offsetof(struct wsgi_request, uri_len);
                }
                else if (!uwsgi_strncmp(ptr, len, "method", 6)) {
Пример #26
0
// this is the command manager
static void uwsgi_imperial_monitor_zeromq_cmd(struct uwsgi_emperor_scanner *ues) {
	int64_t more = 0;
	size_t more_size = sizeof(more);
	int i;
        zmq_msg_t msg[6];

        zmq_msg_init(&msg[0]);
        zmq_msg_init(&msg[1]);
        zmq_msg_init(&msg[2]);
        zmq_msg_init(&msg[3]);
        zmq_msg_init(&msg[4]);
        zmq_msg_init(&msg[5]);

        for(i=0;i<6;i++) {
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3,0,0)
        	zmq_recvmsg(ues->data, &msg[i], ZMQ_DONTWAIT);
#else
        	zmq_recv(ues->data, &msg[i], ZMQ_NOBLOCK);
#endif
                if (zmq_getsockopt(ues->data, ZMQ_RCVMORE, &more, &more_size)) {
                	uwsgi_error("zmq_getsockopt()");
                        break;
                }
                if (!more && i < 4) break;
	}

        if (i < 1) {
		uwsgi_log("[emperor-zeromq] bad message received (command and instance name required)\n");
		return;
	}

	char *ez_cmd = zmq_msg_data(&msg[0]);
        size_t ez_cmd_len = zmq_msg_size(&msg[0]);

	char *ez_name = zmq_msg_data(&msg[1]);
        size_t ez_name_len = zmq_msg_size(&msg[1]);

	char *ez_config = NULL;
        size_t ez_config_len = 0;

	char *ez_uid = NULL;
        size_t ez_uid_len = 0;

	char *ez_gid = NULL;
        size_t ez_gid_len = 0;

	char *ez_socket_name = NULL;
        size_t ez_socket_name_len = 0;

	char *socket_name = NULL;

	// config
	if (i > 1) {
		ez_config = zmq_msg_data(&msg[2]);	
		ez_config_len = zmq_msg_size(&msg[2]);
	}

	// uid
	if (i > 2) {
		ez_uid = zmq_msg_data(&msg[3]);	
		ez_uid_len = zmq_msg_size(&msg[3]);
	}

	// gid
	if (i > 3) {
		ez_gid = zmq_msg_data(&msg[4]);	
		ez_gid_len = zmq_msg_size(&msg[4]);
	}

	// gid
	if (i > 4) {
		ez_socket_name = zmq_msg_data(&msg[5]);	
		ez_socket_name_len = zmq_msg_size(&msg[5]);
	}

	char *name = uwsgi_concat2n(ez_name, ez_name_len, "", 0);

	// ok let's start checking commands
	if (!uwsgi_strncmp(ez_cmd, ez_cmd_len, "touch", 5)) {

		char *config = NULL;
		if (ez_config_len > 0) {
			config = uwsgi_concat2n(ez_config, ez_config_len, "", 0);
		}

		uid_t vassal_uid = 0;
		gid_t vassal_gid = 0;
		if (ez_uid_len > 0) {
			vassal_uid = uwsgi_str_num(ez_uid, ez_uid_len);
		}	
		if (ez_gid_len > 0) {
			vassal_gid = uwsgi_str_num(ez_gid, ez_gid_len);
		}	

		if (ez_socket_name) {
			socket_name = uwsgi_concat2n(ez_socket_name, ez_socket_name_len, "", 0);
		}
		uwsgi_emperor_simple_do(ues, name, config, uwsgi_now(), vassal_uid, vassal_gid, socket_name);
		if (config) {
			free(config);
		}
		if (socket_name) {
			free(socket_name);
		}
	}
	// destroy an instance
	else if (!uwsgi_strncmp(ez_cmd, ez_cmd_len, "destroy", 7)) {
		struct uwsgi_instance *ui = emperor_get(name);
		if (!ui) {
			uwsgi_log("[emperor-zeromq] unknown instance \"%s\"\n", name);
		}
		else {
			emperor_stop(ui);
		}
	}
	else {
		uwsgi_log("[emperor-zeromq] unknown command \"%.*s\"\n", (int)ez_cmd_len, ez_cmd);
	}

	free(name);

	zmq_msg_close(&msg[0]);
        zmq_msg_close(&msg[1]);
        zmq_msg_close(&msg[2]);
        zmq_msg_close(&msg[3]);
        zmq_msg_close(&msg[4]);
        zmq_msg_close(&msg[5]);
}
Пример #27
0
static int uwsgi_glusterfs_request(struct wsgi_request *wsgi_req) {
	char filename[PATH_MAX+1];
	/* Standard GlusterFS request */
        if (!wsgi_req->uh->pktsize) {
                uwsgi_log( "Empty GlusterFS request. skip.\n");
                return -1;
        }

        if (uwsgi_parse_vars(wsgi_req)) {
                return -1;
        }

	// blocks empty paths
	if (wsgi_req->path_info_len == 0 || wsgi_req->path_info_len > PATH_MAX) {
                uwsgi_403(wsgi_req);
                return UWSGI_OK;
	}

        wsgi_req->app_id = uwsgi_get_app_id(wsgi_req, wsgi_req->appid, wsgi_req->appid_len, glusterfs_plugin.modifier1);
	if (wsgi_req->app_id == -1 && !uwsgi.no_default_app && uwsgi.default_app > -1) {
        	if (uwsgi_apps[uwsgi.default_app].modifier1 == glusterfs_plugin.modifier1) {
                	wsgi_req->app_id = uwsgi.default_app;
                }
        }
        if (wsgi_req->app_id == -1) {
                uwsgi_404(wsgi_req);
                return UWSGI_OK;
        }

        struct uwsgi_app *ua = &uwsgi_apps[wsgi_req->app_id];

	memcpy(filename, wsgi_req->path_info, wsgi_req->path_info_len);
	filename[wsgi_req->path_info_len] = 0;

	glfs_fd_t *fd = glfs_open((glfs_t *) ua->interpreter, filename, O_RDONLY);
	if (!fd) {
                uwsgi_404(wsgi_req);
                return UWSGI_OK;
	}
	

	struct stat st;
	if (glfs_fstat(fd, &st)) {
		uwsgi_403(wsgi_req);
                return UWSGI_OK;
	}	

	if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) goto end;
	size_t mime_type_len = 0;
        char *mime_type = uwsgi_get_mime_type(wsgi_req->path_info, wsgi_req->path_info_len, &mime_type_len);
        if (mime_type) {
        	if (uwsgi_response_add_content_type(wsgi_req, mime_type, mime_type_len)) goto end;
        }

        if (uwsgi_response_add_last_modified(wsgi_req, (uint64_t) st.st_mtime)) goto end;
	if (uwsgi_response_add_content_length(wsgi_req, st.st_size)) goto end;

	// skip body on HEAD
	if (uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "HEAD", 4)) {
		size_t remains = st.st_size;
		while(remains > 0) {
			char buf[8192];
			ssize_t rlen = glfs_read (fd, buf, UMIN(remains, 8192), 0);
			if (rlen <= 0) goto end;
			if (uwsgi_response_write_body_do(wsgi_req, buf, rlen)) goto end;
			remains -= rlen;
		}
	}

end:
	glfs_close(fd);
	return UWSGI_OK;
}
Пример #28
0
// dumb/fake tnetstring implementation...all is a string
static int uwsgi_mongrel2_tnetstring_parse(struct wsgi_request *wsgi_req, char *buf, int len) {

	char *ptr = buf;
	char *watermark = buf + len;
	char *key = NULL;
	size_t keylen = 0;
	char *val = NULL;
	size_t vallen = 0;
	uint16_t script_name_len = 0;
	char *query_string = NULL;
	uint16_t query_string_len = 0;
	int async_upload = 0;

	// set an empty SCRIPT_NAME
	wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SCRIPT_NAME", 11, "", 0);

	while (ptr < watermark) {

		ptr = uwsgi_netstring(ptr, len - (ptr - buf), &key, &keylen);
		if (ptr == NULL)
			break;
		// empty keys are not allowed
		if (keylen == 0)
			break;

		if (ptr >= watermark)
			break;

		ptr = uwsgi_netstring(ptr, len - (ptr - buf), &val, &vallen);
		if (ptr == NULL)
			break;


		if (key[0] < 97) {
			if (!uwsgi_strncmp("METHOD", 6, key, keylen)) {
				if (!uwsgi_strncmp("JSON", 4, val, vallen)) {
					return -1;
				}
				wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REQUEST_METHOD", 14, val, vallen);
			}
			else if (!uwsgi_strncmp("VERSION", 7, key, keylen)) {
				wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PROTOCOL", 15, val, vallen);
			}
			else if (!uwsgi_strncmp("QUERY", 5, key, keylen)) {
				wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "QUERY_STRING", 12, val, vallen);
				query_string = val;
				query_string_len = vallen;
			}
			else if (!uwsgi_strncmp("PATH", 4, key, keylen)) {
				wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "PATH_INFO", 9, val + script_name_len, vallen - script_name_len);
				if (query_string_len) {
					char *request_uri = uwsgi_concat3n(val, vallen, "?", 1, query_string, query_string_len);
					wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REQUEST_URI", 11, request_uri, vallen + 1 + query_string_len);
					free(request_uri);
				}
				else {
					wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REQUEST_URI", 11, val, vallen);
				}
			}
		}
		else {
			// add header
			if (!uwsgi_strncmp("host", 4, key, keylen)) {
				char *colon = memchr(val, ':', vallen);
				if (colon) {
					wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, colon + 1, vallen - ((colon + 1) - val));
				}
				else {
					wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, "80", 2);
				}
			}
			else if (!uwsgi_strncmp("content-length", 14, key, keylen)) {
				wsgi_req->post_cl = uwsgi_str_num(val, vallen);
			}
			else if (!uwsgi_strncmp("x-mongrel2-upload-done", 22, key, keylen)) {
				char *post_filename = uwsgi_concat2n(val, vallen, "", 0);
				wsgi_req->post_file = fopen(post_filename, "r");
				if (!wsgi_req->post_file) {
					uwsgi_error_open(post_filename);
					wsgi_req->do_not_log = 1;
				}
				async_upload += 2;
				free(post_filename);
			}
			else if (!uwsgi_strncmp("x-forwarded-for", 15, key, keylen)) {
				char *colon = memchr(val, ',', vallen);
				if (colon) {
					wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REMOTE_ADDR", 11, colon + 1, (colon + 1) - val);
				}
				else {
					wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REMOTE_ADDR", 11, val, vallen);
				}
			}
			else if (!uwsgi_strncmp("x-mongrel2-upload-start", 23, key, keylen)) {
				async_upload += 1;
			}
			wsgi_req->uh->pktsize += proto_base_add_uwsgi_header(wsgi_req, key, keylen, val, vallen);
		}
	}

	wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_NAME", 11, uwsgi.hostname, uwsgi.hostname_len);

	if (query_string == NULL) {
		// always set QUERY_STRING
		wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "QUERY_STRING", 12, "", 0);
	}

	// reject uncomplete upload
	if (async_upload == 1) {
		return -1;
	}
	return 0;
}
Пример #29
0
static int uwsgi_webdav_request(struct wsgi_request *wsgi_req) {

	if (!udav.mountpoints) {
		uwsgi_500(wsgi_req);
		return -1;
	}

	if (uwsgi_parse_vars(wsgi_req)) {
		return -1;
	}

	if (wsgi_req->path_info_len == 0) {
		uwsgi_403(wsgi_req);
		return UWSGI_OK;
	}

	wsgi_req->app_id = uwsgi_get_app_id(wsgi_req, wsgi_req->appid, wsgi_req->appid_len, webdav_plugin.modifier1);
        if (wsgi_req->app_id == -1) {
                uwsgi_403(wsgi_req);
                return UWSGI_OK;
        }

	// non lockables methods...

	if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "OPTIONS", 7)) {
		return uwsgi_wevdav_manage_options(wsgi_req);
	}

	if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "GET", 3)) {
		return uwsgi_wevdav_manage_get(wsgi_req, 1);
	}

	if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "HEAD", 4)) {
		return uwsgi_wevdav_manage_get(wsgi_req, 0);
	}

	if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "PROPFIND", 8)) {
		if (wsgi_req->post_cl > 0) {
			ssize_t body_len = 0;
			char *body = uwsgi_request_body_read(wsgi_req, wsgi_req->post_cl, &body_len);
#ifdef UWSGI_DEBUG
			uwsgi_log("%.*s\n", body_len, body);
#endif
			xmlDoc *doc = xmlReadMemory(body, body_len, NULL, NULL, 0);
			if (!doc) goto end;
			uwsgi_wevdav_manage_propfind(wsgi_req, doc);
			xmlFreeDoc(doc);
		}
		else {
			uwsgi_wevdav_manage_propfind(wsgi_req, NULL);
		}
	}

	if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "REPORT", 6)) {
                if (wsgi_req->post_cl > 0) {
                        ssize_t body_len = 0;
                        char *body = uwsgi_request_body_read(wsgi_req, wsgi_req->post_cl, &body_len);
#ifdef UWSGI_DEBUG
                        uwsgi_log("%.*s\n", body_len, body);
#endif
                        xmlDoc *doc = xmlReadMemory(body, body_len, NULL, NULL, 0);
                        if (!doc) goto end;
                        xmlFreeDoc(doc);
                }
        }


	// lockable methods ...
	// check for locking

	if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "PUT", 3)) {
		return uwsgi_wevdav_manage_put(wsgi_req);
	}

	if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "DELETE", 6)) {
		return uwsgi_wevdav_manage_delete(wsgi_req);
	}

	if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "MKCOL", 5)) {
		return uwsgi_wevdav_manage_mkcol(wsgi_req);
	}

	if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "MKCALENDAR", 10)) {
		if (wsgi_req->post_cl == 0)
                        goto end;
                ssize_t body_len = 0;
                char *body = uwsgi_request_body_read(wsgi_req, wsgi_req->post_cl, &body_len);
#ifdef UWSGI_DEBUG
                uwsgi_log("%.*s\n", body_len, body);
#endif
                xmlDoc *doc = xmlReadMemory(body, body_len, NULL, NULL, 0);
                if (!doc) goto end;
                uwsgi_wevdav_manage_mkcalendar(wsgi_req, doc);
                xmlFreeDoc(doc);
	}

	if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "COPY", 4)) {
		return uwsgi_wevdav_manage_copy(wsgi_req);
	}

	if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "MOVE", 4)) {
		return uwsgi_wevdav_manage_move(wsgi_req);
	}

	if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "LOCK", 4)) {
		if (wsgi_req->post_cl > 0) {
			ssize_t body_len = 0;
                	char *body = uwsgi_request_body_read(wsgi_req, wsgi_req->post_cl, &body_len);
#ifdef UWSGI_DEBUG
                	uwsgi_log("%.*s\n", body_len, body);
#endif
			xmlDoc *doc = xmlReadMemory(body, body_len, NULL, NULL, 0);
			if (!doc) goto end;
                	xmlFreeDoc(doc);
		}	
		return uwsgi_wevdav_manage_lock(wsgi_req);
	}

	if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "PROPPATCH", 9)) {
                if (wsgi_req->post_cl == 0)
                        goto end;
                ssize_t body_len = 0;
                char *body = uwsgi_request_body_read(wsgi_req, wsgi_req->post_cl, &body_len);
#ifdef UWSGI_DEBUG
                uwsgi_log("%.*s\n", body_len, body);
#endif
                xmlDoc *doc = xmlReadMemory(body, body_len, NULL, NULL, 0);
                if (!doc) goto end;
		uwsgi_wevdav_manage_proppatch(wsgi_req, doc);
                xmlFreeDoc(doc);
        }

end:
	return UWSGI_OK;
}
Пример #30
0
struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slot **slot, struct uwsgi_subscribe_req *usr) {

	struct uwsgi_subscribe_slot *current_slot = uwsgi_get_subscribe_slot(slot, usr->key, usr->keylen), *old_slot = NULL, *a_slot;
	struct uwsgi_subscribe_node *node, *old_node = NULL;

	if (usr->address_len > 0xff || usr->address_len == 0)
		return NULL;

#ifdef UWSGI_SSL
	if (uwsgi.subscriptions_sign_check_dir) {
		if (usr->sign_len == 0 || usr->base_len == 0)
			return NULL;
	}
#endif

	if (current_slot) {
#ifdef UWSGI_SSL
		if (uwsgi.subscriptions_sign_check_dir && !uwsgi_subscription_sign_check(current_slot, usr)) {
			return NULL;
		}
#endif
		node = current_slot->nodes;
		while (node) {
			if (!uwsgi_strncmp(node->name, node->len, usr->address, usr->address_len)) {
#ifdef UWSGI_SSL
				// this should avoid sending sniffed packets...
				if (uwsgi.subscriptions_sign_check_dir && usr->unix_check <= node->unix_check) {
					uwsgi_log("[uwsgi-subscription for pid %d] invalid (sniffed ?) packet sent for slot: %.*s node: %.*s unix_check: %lu\n", (int) uwsgi.mypid, usr->keylen, usr->key, usr->address_len, usr->address, (unsigned long) usr->unix_check);
					return NULL;
				}
#endif
				// remove death mark and update cores and load
				node->death_mark = 0;
				node->last_check = uwsgi_now();
				node->cores = usr->cores;
				node->load = usr->load;
				node->weight = usr->weight;
				if (!node->weight)
					node->weight = 1;
				node->last_requests = 0;
				return node;
			}
			old_node = node;
			node = node->next;
		}

#ifdef UWSGI_SSL
		if (uwsgi.subscriptions_sign_check_dir && usr->unix_check < (uwsgi_now() - (time_t) uwsgi.subscriptions_sign_check_tolerance)) {
			uwsgi_log("[uwsgi-subscription for pid %d] invalid (sniffed ?) packet sent for slot: %.*s node: %.*s unix_check: %lu\n", (int) uwsgi.mypid, usr->keylen, usr->key, usr->address_len, usr->address, (unsigned long) usr->unix_check);
			return NULL;
		}
#endif

		node = uwsgi_malloc(sizeof(struct uwsgi_subscribe_node));
		node->len = usr->address_len;
		node->modifier1 = usr->modifier1;
		node->modifier2 = usr->modifier2;
		node->requests = 0;
		node->last_requests = 0;
		node->transferred = 0;
		node->reference = 0;
		node->death_mark = 0;
		node->failcnt = 0;
		node->cores = usr->cores;
		node->load = usr->load;
		node->weight = usr->weight;
		node->unix_check = usr->unix_check;
		if (!node->weight)
			node->weight = 1;
		node->wrr = 0;
		node->last_check = uwsgi_now();
		node->slot = current_slot;
		memcpy(node->name, usr->address, usr->address_len);
		if (old_node) {
			old_node->next = node;
		}
		node->next = NULL;
		uwsgi_log("[uwsgi-subscription for pid %d] %.*s => new node: %.*s\n", (int) uwsgi.mypid, usr->keylen, usr->key, usr->address_len, usr->address);
		return node;
	}
	else {
#ifdef UWSGI_SSL
		FILE *kf = NULL;
		if (uwsgi.subscriptions_sign_check_dir) {
			if (usr->unix_check < (uwsgi_now() - (time_t) uwsgi.subscriptions_sign_check_tolerance)) {
				uwsgi_log("[uwsgi-subscription for pid %d] invalid (sniffed ?) packet sent for slot: %.*s node: %.*s unix_check: %lu\n", (int) uwsgi.mypid, usr->keylen, usr->key, usr->address_len, usr->address, (unsigned long) usr->unix_check);
				return NULL;
			}
			char *keyfile = uwsgi_sanitize_cert_filename(uwsgi.subscriptions_sign_check_dir, usr->key, usr->keylen);
			kf = fopen(keyfile, "r");
			free(keyfile);
			if (!kf)
				return NULL;

		}
#endif
		current_slot = uwsgi_malloc(sizeof(struct uwsgi_subscribe_slot));
		uint32_t hash = djb33x_hash(usr->key, usr->keylen);
		int hash_key = hash % 0xffff;
		current_slot->hash = hash_key;
#ifdef UWSGI_SSL
		if (uwsgi.subscriptions_sign_check_dir) {
			current_slot->sign_public_key = PEM_read_PUBKEY(kf, NULL, NULL, NULL);
			fclose(kf);
			if (!current_slot->sign_public_key) {
				uwsgi_log("unable to load public key for %.*s\n", usr->keylen, usr->key);
				free(current_slot);
				return NULL;
			}
			current_slot->sign_ctx = EVP_MD_CTX_create();
			if (!current_slot->sign_ctx) {
				uwsgi_log("unable to initialize EVP context for %.*s\n", usr->keylen, usr->key);
				EVP_PKEY_free(current_slot->sign_public_key);
				free(current_slot);
				return NULL;
			}

			if (!uwsgi_subscription_sign_check(current_slot, usr)) {
				EVP_PKEY_free(current_slot->sign_public_key);
				EVP_MD_CTX_destroy(current_slot->sign_ctx);
				free(current_slot);
				return NULL;
			}
		}
#endif
		current_slot->keylen = usr->keylen;
		memcpy(current_slot->key, usr->key, usr->keylen);
		current_slot->key[usr->keylen] = 0;
		current_slot->hits = 0;

		current_slot->nodes = uwsgi_malloc(sizeof(struct uwsgi_subscribe_node));
		current_slot->nodes->slot = current_slot;
		current_slot->nodes->len = usr->address_len;
		current_slot->nodes->reference = 0;
		current_slot->nodes->requests = 0;
		current_slot->nodes->last_requests = 0;
		current_slot->nodes->transferred = 0;
		current_slot->nodes->death_mark = 0;
		current_slot->nodes->failcnt = 0;
		current_slot->nodes->modifier1 = usr->modifier1;
		current_slot->nodes->modifier2 = usr->modifier2;
		current_slot->nodes->cores = usr->cores;
		current_slot->nodes->load = usr->load;
		current_slot->nodes->weight = usr->weight;
		current_slot->nodes->unix_check = usr->unix_check;
		if (!current_slot->nodes->weight)
			current_slot->nodes->weight = 1;
		current_slot->nodes->wrr = 0;
		memcpy(current_slot->nodes->name, usr->address, usr->address_len);
		current_slot->nodes->last_check = uwsgi_now();

		current_slot->nodes->next = NULL;

		a_slot = slot[hash_key];
		while (a_slot) {
			old_slot = a_slot;
			a_slot = a_slot->next;
		}


		if (old_slot) {
			old_slot->next = current_slot;
		}

		current_slot->prev = old_slot;
		current_slot->next = NULL;


		if (!slot[hash_key] || current_slot->prev == NULL) {
			slot[hash_key] = current_slot;
		}

		uwsgi_log("[uwsgi-subscription for pid %d] new pool: %.*s (hash key: %d)\n", (int) uwsgi.mypid, usr->keylen, usr->key, current_slot->hash);
		uwsgi_log("[uwsgi-subscription for pid %d] %.*s => new node: %.*s\n", (int) uwsgi.mypid, usr->keylen, usr->key, usr->address_len, usr->address);
		return current_slot->nodes;
	}

}