Beispiel #1
0
int uwsgi_add_expires_uri(struct wsgi_request *wsgi_req, struct stat *st) {

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

	while (udd) {
		if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->uri, wsgi_req->uri_len) >= 0) {
			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_uri_mtime;
	while (udd) {
		if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->uri, wsgi_req->uri_len) >= 0) {
			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;
}
Beispiel #2
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;
}
Beispiel #3
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;
	}
}
Beispiel #4
0
int uwsgi_cr_map_use_cache(struct uwsgi_corerouter *ucr, struct corerouter_peer *peer) {
	uint64_t hits = 0;
	uwsgi_rlock(ucr->cache->lock);
	char *value = uwsgi_cache_get4(ucr->cache, peer->key, peer->key_len, &peer->instance_address_len, &hits);
	if (!value) goto end;
	peer->tmp_socket_name = uwsgi_concat2n(value, peer->instance_address_len, "", 0);
	size_t nodes = uwsgi_str_occurence(peer->tmp_socket_name, peer->instance_address_len, '|');
	if (nodes > 0) {
		size_t choosen_node = hits % (nodes+1);
		size_t choosen_node_len = 0;
		peer->instance_address = uwsgi_str_split_nget(peer->tmp_socket_name, peer->instance_address_len, '|', choosen_node, &choosen_node_len);
		if (!peer->instance_address) goto end;
		peer->instance_address_len = choosen_node_len;
	}
	else {
		peer->instance_address = peer->tmp_socket_name;
	}
	char *cs_mod = uwsgi_str_contains(peer->instance_address, peer->instance_address_len, ',');
	if (cs_mod) {
		peer->modifier1 = uwsgi_str_num(cs_mod + 1, (peer->instance_address_len - (cs_mod - peer->instance_address)) - 1);
		peer->instance_address_len = (cs_mod - peer->instance_address);
	}
end:
	uwsgi_rwunlock(ucr->cache->lock);
	return 0;
}
Beispiel #5
0
int uwsgi_cr_map_use_cache(struct uwsgi_corerouter *ucr, struct corerouter_session *cr_session) {
	cr_session->instance_address = uwsgi_cache_get(cr_session->hostname, cr_session->hostname_len, &cr_session->instance_address_len);
	char *cs_mod = uwsgi_str_contains(cr_session->instance_address, cr_session->instance_address_len, ',');
	if (cs_mod) {
		cr_session->modifier1 = uwsgi_str_num(cs_mod + 1, (cr_session->instance_address_len - (cs_mod - cr_session->instance_address)) - 1);
		cr_session->instance_address_len = (cs_mod - cr_session->instance_address);
	}
	return 0;
}
Beispiel #6
0
int uwsgi_fr_map_use_cache(struct fastrouter_session *fr_session, char **magic_table) {
	fr_session->instance_address = uwsgi_cache_get(fr_session->hostname, fr_session->hostname_len, &fr_session->instance_address_len);
	char *cs_mod = uwsgi_str_contains(fr_session->instance_address, fr_session->instance_address_len, ',');
	if (cs_mod) {
		fr_session->modifier1 = uwsgi_str_num(cs_mod + 1, (fr_session->instance_address_len - (cs_mod - fr_session->instance_address)) - 1);
		fr_session->instance_address_len = (cs_mod - fr_session->instance_address);
	}
	return 0;
}
Beispiel #7
0
static size_t memcached_firstline_parse(char *buf, size_t len) {
	// check for "VALUE x 0 0"
	if (len < 11) return 0;
	char *flags = memchr(buf + 6, ' ', len-6);
	if (!flags) return 0;
	size_t skip = (flags-buf)+1;
	if (skip+1 >= len) return 0;
	char *bytes = memchr(buf + skip + 1, ' ', len - (skip+1));
	if (!bytes) return 0;
	skip = (bytes-buf)+1;
	if (skip+1 > len) return 0;
	char *bytes_end = memchr(buf + skip + 1, ' ', len - (skip+1));
	if (bytes_end) {
		return uwsgi_str_num(bytes + 1, bytes_end - (bytes+1));
	}
	else {
		return uwsgi_str_num(bytes + 1, len-skip);
	}
}
Beispiel #8
0
int uwsgi_fr_map_use_cs(struct fastrouter_session *fr_session, char **magic_table) {
	if (uwsgi.p[ufr.code_string_modifier1]->code_string) {
		fr_session->instance_address = uwsgi.p[ufr.code_string_modifier1]->code_string("uwsgi_fastrouter", ufr.code_string_code, ufr.code_string_function, fr_session->hostname, fr_session->hostname_len);
		if (fr_session->instance_address) {
			fr_session->instance_address_len = strlen(fr_session->instance_address);
			char *cs_mod = uwsgi_str_contains(fr_session->instance_address, fr_session->instance_address_len, ',');
			if (cs_mod) {
				fr_session->modifier1 = uwsgi_str_num(cs_mod + 1, (fr_session->instance_address_len - (cs_mod - fr_session->instance_address)) - 1);
				fr_session->instance_address_len = (cs_mod - fr_session->instance_address);
			}
		}
	}
	return 0;
}
Beispiel #9
0
int uwsgi_cr_map_use_cs(struct uwsgi_corerouter *ucr, struct corerouter_session *cr_session) {
	if (uwsgi.p[ucr->code_string_modifier1]->code_string) {
		char *name = uwsgi_concat2("uwsgi_", ucr->short_name);
		cr_session->instance_address = uwsgi.p[ucr->code_string_modifier1]->code_string(name, ucr->code_string_code, ucr->code_string_function, cr_session->hostname, cr_session->hostname_len);
		free(name);
		if (cr_session->instance_address) {
			cr_session->instance_address_len = strlen(cr_session->instance_address);
			char *cs_mod = uwsgi_str_contains(cr_session->instance_address, cr_session->instance_address_len, ',');
			if (cs_mod) {
				cr_session->modifier1 = uwsgi_str_num(cs_mod + 1, (cr_session->instance_address_len - (cs_mod - cr_session->instance_address)) - 1);
				cr_session->instance_address_len = (cs_mod - cr_session->instance_address);
			}
		}
	}
	return 0;
}
Beispiel #10
0
int uwsgi_cr_map_use_cs(struct uwsgi_corerouter *ucr, struct corerouter_peer *peer) {
	if (uwsgi.p[ucr->code_string_modifier1]->code_string) {
		char *name = uwsgi_concat2("uwsgi_", ucr->short_name);
		peer->instance_address = uwsgi.p[ucr->code_string_modifier1]->code_string(name, ucr->code_string_code, ucr->code_string_function, peer->key, peer->key_len);
		free(name);
		if (peer->instance_address) {
			peer->instance_address_len = strlen(peer->instance_address);
			char *cs_mod = uwsgi_str_contains(peer->instance_address, peer->instance_address_len, ',');
			if (cs_mod) {
				peer->modifier1 = uwsgi_str_num(cs_mod + 1, (peer->instance_address_len - (cs_mod - peer->instance_address)) - 1);
				peer->instance_address_len = (cs_mod - peer->instance_address);
			}
		}
	}
	return 0;
}
Beispiel #11
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);
	}
}
Beispiel #12
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;
	}
}
Beispiel #13
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]);
}
Beispiel #14
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;
}
Beispiel #15
0
static int scgi_parse(struct wsgi_request *wsgi_req) {
	char *buf = wsgi_req->proto_parser_buf;
	size_t len = wsgi_req->proto_parser_pos;
	size_t i;
	size_t scgi_len = 0;
	for(i=0;i<len;i++) {
		if (buf[i] == ':') {
			scgi_len = uwsgi_str_num(buf, i);
			if (scgi_len == 0) return -1;
			goto keyval;
		}
	}
	return 0;

keyval:

	if (i + scgi_len + 1 > len) {
		return 0;
	}

	i++;

	size_t vars = i;
	char *key = buf + i;
	size_t keylen = 0;
	char *value = NULL;
	size_t vallen = 0;
	for(i=vars;i<vars+scgi_len;i++) {
		if (key == NULL) {
			key = buf + i;
		}
		else if (keylen > 0 && value == NULL) {
			value = buf + i;
		}
		if (buf[i] == 0) {
			if (value) {
				vallen = (buf+i) - value;
				uint16_t pktsize = proto_base_add_uwsgi_var(wsgi_req, key, keylen, value, vallen);
                		if (pktsize == 0) return -1;
                		wsgi_req->uh->pktsize += pktsize;
				key = NULL;
				value = NULL;
				keylen = 0;
				vallen = 0;
			}
			else {
				keylen = (buf+i) - key;
				value = NULL;
			}
		}
	}


	if (buf[i] == ',') {
		if (len > i+1) {
			wsgi_req->proto_parser_remains = len-(i+1);
                        wsgi_req->proto_parser_remains_buf = buf + i + 1;			
		}
		return 1;
	}
	return -1;
}
Beispiel #16
0
void uwsgi_subscribe(char *subscription, uint8_t cmd) {

	int subfile_size;
	int i;
	char *key = NULL;
	int keysize = 0;
	char *modifier1 = NULL;
	int modifier1_len = 0;
	char *socket_name = NULL;
	char *udp_address = subscription;
	char *udp_port = NULL;
	char *subscription_key = NULL;
	char *sign = NULL;

	// check for explicit socket_name
	char *equal = strchr(subscription, '=');
	if (equal) {
		socket_name = subscription;
		if (socket_name[0] == '=') {
			equal = strchr(socket_name + 1, '=');
			if (!equal)
				return;
			*equal = '\0';
			struct uwsgi_socket *us = uwsgi_get_shared_socket_by_num(atoi(socket_name + 1));
			if (!us)
				return;
			socket_name = us->name;
		}
		*equal = '\0';
		udp_address = equal + 1;
	}

	// check for unix socket
	if (udp_address[0] != '/') {
		udp_port = strchr(udp_address, ':');
		if (!udp_port) {
			if (equal)
				*equal = '=';
			return;
		}
		subscription_key = strchr(udp_port + 1, ':');
	}
	else {
		subscription_key = strchr(udp_address + 1, ':');
	}

	if (!subscription_key) {
		if (equal)
			*equal = '=';
		return;
	}

	udp_address = uwsgi_concat2n(udp_address, subscription_key - udp_address, "", 0);

	if (subscription_key[1] == '@') {
		if (!uwsgi_file_exists(subscription_key + 2))
			goto clear;
		char *lines = uwsgi_open_and_read(subscription_key + 2, &subfile_size, 1, NULL);
		if (subfile_size > 0) {
			key = lines;
			for (i = 0; i < subfile_size; i++) {
				if (lines[i] == 0) {
					if (keysize > 0) {
						if (key[0] != '#' && key[0] != '\n') {
							modifier1 = strchr(key, ',');
							if (modifier1) {
								modifier1[0] = 0;
								modifier1++;
								modifier1_len = strlen(modifier1);
								keysize = strlen(key);
							}
							uwsgi_send_subscription(udp_address, key, keysize, uwsgi_str_num(modifier1, modifier1_len), 0, cmd, socket_name, sign);
							modifier1 = NULL;
							modifier1_len = 0;
						}
					}
					break;
				}
				else if (lines[i] == '\n') {
					if (keysize > 0) {
						if (key[0] != '#' && key[0] != '\n') {
							lines[i] = 0;
							modifier1 = strchr(key, ',');
							if (modifier1) {
								modifier1[0] = 0;
								modifier1++;
								modifier1_len = strlen(modifier1);
								keysize = strlen(key);
							}
							uwsgi_send_subscription(udp_address, key, keysize, uwsgi_str_num(modifier1, modifier1_len), 0, cmd, socket_name, sign);
							modifier1 = NULL;
							modifier1_len = 0;
							lines[i] = '\n';
						}
					}
					key = lines + i + 1;
					keysize = 0;
					continue;
				}
				keysize++;
			}

			free(lines);
		}
	}
	else {
		modifier1 = strchr(subscription_key + 1, ',');
		if (modifier1) {
			modifier1[0] = 0;
			modifier1++;

			sign = strchr(modifier1 + 1, ',');
			if (sign) {
				*sign = 0;
				sign++;
			}
			modifier1_len = strlen(modifier1);
		}

		uwsgi_send_subscription(udp_address, subscription_key + 1, strlen(subscription_key + 1), uwsgi_str_num(modifier1, modifier1_len), 0, cmd, socket_name, sign);
		if (modifier1)
			modifier1[-1] = ',';
		if (sign)
			sign[-1] = ',';
	}

clear:
	if (equal)
		*equal = '=';
	free(udp_address);

}
Beispiel #17
0
static struct uwsgi_buffer *uwsgi_ruby_backtrace(struct wsgi_request *wsgi_req) {
	VALUE err = rb_errinfo();
	VALUE ary = rb_funcall(err, rb_intern("backtrace"), 0);
	int i;
	struct uwsgi_buffer *ub = uwsgi_buffer_new(4096);
	char *filename = NULL;
	char *function = NULL;
	for (i=0; i<RARRAY_LEN(ary); i++) {
		char *bt = RSTRING_PTR(RARRAY_PTR(ary)[i]);
		// ok let's start the C dance to parse the backtrace
		char *colon = strchr(bt, ':');
		if (!colon) continue;
		filename = uwsgi_concat2n(bt, (int) (colon-bt), "", 0);
		uint16_t filename_len = colon-bt;
		colon++; if (*colon == 0) goto error;
		char *lineno_ptr = colon;
		colon = strchr(lineno_ptr, ':');
		if (!colon) goto error;
		int64_t lineno = uwsgi_str_num(lineno_ptr, (int) (colon-lineno_ptr));
		colon++; if (*colon == 0) goto error;
		colon = strchr(lineno_ptr, '`');
		if (!colon) goto error;
		colon++; if (*colon == 0) goto error;
		char *function_ptr = colon;
		char *function_end = strchr(function_ptr, '\'');
		if (!function_end) goto error;
		function = uwsgi_concat2n(function_ptr, (int) (function_end-function_ptr), "", 0);
		uint16_t function_len = function_end-function_ptr;

		if (uwsgi_buffer_u16le(ub, filename_len)) goto error;
		if (uwsgi_buffer_append(ub, filename, filename_len)) goto error;
		if (uwsgi_buffer_append_valnum(ub, lineno)) goto error;
		if (uwsgi_buffer_u16le(ub, function_len)) goto error;
		if (uwsgi_buffer_append(ub, function, function_len)) goto error;

		// in ruby we do not have text/code nor custom
		if (uwsgi_buffer_u16le(ub, 0)) goto error;
		if (uwsgi_buffer_append(ub, "", 0)) goto error;
		if (uwsgi_buffer_u16le(ub, 0)) goto error;
		if (uwsgi_buffer_append(ub, "", 0)) goto error;

		free(filename);
		filename = NULL;
		free(function);
		function = NULL;
	}

	return ub;

error:
	uwsgi_buffer_destroy(ub);

	if (filename) {
		free(filename);
	}

	if (function) {
		free(function);
	}

	return NULL;
}
Beispiel #18
0
static int uwsgi_webdav_add_props(struct wsgi_request *wsgi_req, xmlNode *req_prop, xmlNode * multistatus, xmlNsPtr dav_ns, char *uri, char *filename, int with_values) {
	struct stat st;
	if (stat(filename, &st)) {
		uwsgi_error("uwsgi_webdav_add_props()/stat()");
		return -1;
	}

	int is_collection = 0;

	xmlNode *response = xmlNewChild(multistatus, dav_ns, BAD_CAST "response", NULL);
	uint16_t uri_len = strlen(uri) ;
	char *encoded_uri = uwsgi_malloc( (uri_len * 3) + 1);
	http_url_encode(uri, &uri_len, encoded_uri);
	encoded_uri[uri_len] = 0;
	xmlNewChild(response, dav_ns, BAD_CAST "href", BAD_CAST encoded_uri);
	free(encoded_uri);
	xmlNode *r_propstat = xmlNewChild(response, dav_ns, BAD_CAST "propstat", NULL);
	char *r_status = uwsgi_concat2n(wsgi_req->protocol, wsgi_req->protocol_len, " 200 OK", 7);
	xmlNewChild(r_propstat, dav_ns, BAD_CAST "status", BAD_CAST r_status);
	free(r_status);

	xmlNode *r_prop = xmlNewChild(r_propstat, dav_ns, BAD_CAST "prop", NULL);

	if (with_values) {
		if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "displayname")) {
			char *base_uri = uwsgi_get_last_char(uri, '/');
			if (base_uri) {
				xmlNewChild(r_prop, dav_ns, BAD_CAST "displayname", BAD_CAST base_uri+1);
			}
			else {
				xmlNewChild(r_prop, dav_ns, BAD_CAST "displayname", BAD_CAST uri);
			}

		}

		if (S_ISDIR(st.st_mode)) is_collection = 1;

		xmlNode *r_type = NULL;

		if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "resourcetype")) {
			r_type = xmlNewChild(r_prop, dav_ns, BAD_CAST "resourcetype", NULL);
			if (is_collection) {
				xmlNewChild(r_type, dav_ns, BAD_CAST "collection", NULL);
				is_collection = 1;
			}
		}


		if (!is_collection) {
			if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "getcontentlength")) {
				char *r_contentlength = uwsgi_num2str(st.st_size);
				xmlNewChild(r_prop, dav_ns, BAD_CAST "getcontentlength", BAD_CAST r_contentlength);
				free(r_contentlength);
			}
			if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "getcontenttype")) {
				size_t mime_type_len = 0;
				char *mime_type = uwsgi_get_mime_type(filename, strlen(filename), &mime_type_len);
				if (mime_type) {
					char *r_ctype = uwsgi_concat2n(mime_type, mime_type_len, "", 0);
					xmlNewTextChild(r_prop, dav_ns, BAD_CAST "getcontenttype", BAD_CAST r_ctype);
					free(r_ctype);
				}
			}
		}

		if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "creationdate")) {
			// there is no creation date on UNIX/POSIX, ctime is the nearest thing...
			char *cdate = uwsgi_webdav_new_date(st.st_ctime);
			if (cdate) {
				xmlNewTextChild(r_prop, dav_ns, BAD_CAST "creationdate", BAD_CAST cdate);
				free(cdate);
			}
		}

		if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "getlastmodified")) {
			char *mdate = uwsgi_webdav_new_date(st.st_mtime);
			if (mdate) {
				xmlNewTextChild(r_prop, dav_ns, BAD_CAST "getlastmodified", BAD_CAST mdate);
				free(mdate);
			}
		}

		if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "getetag")) {
			char *etag = uwsgi_num2str(st.st_mtime);
			xmlNewTextChild(r_prop, dav_ns, BAD_CAST "getetag", BAD_CAST etag);
			free(etag);
		}

		if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "executable")) {
			xmlNewChild(r_prop, dav_ns, BAD_CAST "executable", NULL);
		}

		if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "owner")) {
			xmlNewTextChild(r_prop, dav_ns, BAD_CAST "owner", NULL);
		}

		if (wsgi_req->remote_user_len > 0) {

			if (udav.principal_base) {
				if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "current-user-principal")) {
					char *current_user_principal = uwsgi_concat2n(udav.principal_base, strlen(udav.principal_base), wsgi_req->remote_user, wsgi_req->remote_user_len);
					xmlNode *cup = xmlNewChild(r_prop, dav_ns, BAD_CAST "current-user-principal", NULL);
					xmlNewTextChild(cup, dav_ns, BAD_CAST "href", BAD_CAST current_user_principal);
					if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "resourcetype")) {
						if (!strcmp(current_user_principal, uri)) {
							xmlNewChild(r_type, dav_ns, BAD_CAST "principal", NULL);
						}
					}
					free(current_user_principal);
				}
			}

			if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "current-user-privilege-set")) {
				xmlNode *cups = xmlNewChild(r_prop, dav_ns, BAD_CAST "current-user-privilege-set", NULL);
				xmlNode *privilege = xmlNewChild(cups, dav_ns, BAD_CAST "privilege", NULL);	
				xmlNewChild(privilege, dav_ns, BAD_CAST "all", NULL);
				xmlNewChild(privilege, dav_ns, BAD_CAST "read", NULL);
				xmlNewChild(privilege, dav_ns, BAD_CAST "write", NULL);
				xmlNewChild(privilege, dav_ns, BAD_CAST "write-content", NULL);
				xmlNewChild(privilege, dav_ns, BAD_CAST "write-properties", NULL);
			}
		}

		if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "supported-report-set")) {
			xmlNode *report_set = xmlNewChild(r_prop, dav_ns, BAD_CAST "supported-report-set", NULL);
			xmlNode *supported_report = xmlNewChild(report_set, dav_ns, BAD_CAST "supported-report", NULL);
			xmlNewChild(supported_report, dav_ns, BAD_CAST "report", BAD_CAST "principal-property-search");
			supported_report = xmlNewChild(report_set, dav_ns, BAD_CAST "supported-report", NULL);
			xmlNewChild(supported_report, dav_ns, BAD_CAST "report", BAD_CAST "sync-collection");
			supported_report = xmlNewChild(report_set, dav_ns, BAD_CAST "supported-report", NULL);
			xmlNewChild(supported_report, dav_ns, BAD_CAST "report", BAD_CAST "expand-property");
			supported_report = xmlNewChild(report_set, dav_ns, BAD_CAST "supported-report", NULL);
			xmlNewChild(supported_report, dav_ns, BAD_CAST "report", BAD_CAST "principal-search-property-set");
		}

		uwsgi_webdav_foreach_prop(udav.add_prop, req_prop, r_prop, 0, NULL );
                uwsgi_webdav_foreach_prop(udav.add_prop_href, req_prop, r_prop, 1, NULL);
                uwsgi_webdav_foreach_prop(udav.add_prop_comp,req_prop, r_prop, 2 , NULL);

		uwsgi_webdav_foreach_prop(udav.add_rtype_prop,req_prop, r_type, 0, "resourcetype");

		if (is_collection) {
			uwsgi_webdav_foreach_prop(udav.add_rtype_collection_prop,req_prop, r_type, 0, "resourcetype");
			uwsgi_webdav_foreach_prop(udav.add_collection_prop,req_prop, r_prop, 0, NULL);
			uwsgi_webdav_foreach_prop(udav.add_collection_prop_href,req_prop, r_prop, 1, NULL);
			uwsgi_webdav_foreach_prop(udav.add_collection_prop_comp,req_prop, r_prop, 2, NULL);
		}
		else {
			uwsgi_webdav_foreach_prop(udav.add_rtype_object_prop,req_prop, r_type, 0, "resourcetype");
			uwsgi_webdav_foreach_prop(udav.add_object_prop,req_prop, r_prop, 0, NULL);
			uwsgi_webdav_foreach_prop(udav.add_object_prop_href,req_prop, r_prop, 1, NULL);
			uwsgi_webdav_foreach_prop(udav.add_object_prop_comp,req_prop, r_prop, 2, NULL);
		}
	}
	else {
		xmlNewChild(r_prop, dav_ns, BAD_CAST "displayname", NULL);
		xmlNewChild(r_prop, dav_ns, BAD_CAST "resourcetype", NULL);
		if (!S_ISDIR(st.st_mode)) {
			xmlNewChild(r_prop, dav_ns, BAD_CAST "getcontentlength", NULL);
			xmlNewChild(r_prop, dav_ns, BAD_CAST "getcontenttype", NULL);
		}
		xmlNewChild(r_prop, dav_ns, BAD_CAST "creationdate", NULL);
		xmlNewChild(r_prop, dav_ns, BAD_CAST "getlastmodified", NULL);
		xmlNewChild(r_prop, dav_ns, BAD_CAST "supported-report-set", NULL);
		if (wsgi_req->remote_user_len > 0) {
			xmlNewChild(r_prop, dav_ns, BAD_CAST "current-user-privilege-set", NULL);
			if (udav.principal_base) {
				xmlNewChild(r_prop, dav_ns, BAD_CAST "current-user-principal", NULL);
			}
		}
	}

#if defined(__linux__) || defined(__APPLE__)
	// get xattr for user.uwsgi.webdav.
#if defined(__linux__)
	ssize_t rlen = listxattr(filename, NULL, 0);
#elif defined(__APPLE__)
	ssize_t rlen = listxattr(filename, NULL, 0, 0);
#endif
	// do not return -1 as the previous xml is valid !!!
	if (rlen <= 0) return 0;
	// use calloc to avoid races
	char *xattrs = uwsgi_calloc(rlen);
#if defined(__linux__)
	if (listxattr(filename, xattrs, rlen) <= 0) {
#elif defined(__APPLE__)
	if (listxattr(filename, xattrs, rlen, 0) <= 0) {
#endif
		free(xattrs);
		return 0;
	}
	// parse the name list
	ssize_t i;
	char *key = NULL;
	for(i=0;i<rlen;i++) {
		// check for wrong condition
		if (xattrs[i] == 0 && key == NULL) break;
		if (key && xattrs[i] == 0) {
			if (!uwsgi_starts_with(key, strlen(key), "user.uwsgi.webdav.", 18)) {
				if (uwsgi_string_list_has_item(udav.skip_prop, key + 18, strlen(key + 18))) continue;
				xmlNsPtr xattr_ns = NULL;
				// does it has a namespace ?
				char *separator = strchr(key + 18, '|');
				char *xattr_key = key + 18;
				if (separator) {
					xattr_key = separator + 1;
					*separator = 0;
					if (!uwsgi_webdav_prop_requested(req_prop, key + 18, xattr_key)) continue;
				}
				else {
					if (!uwsgi_webdav_prop_requested(req_prop, NULL, xattr_key)) continue;
				}
				xmlNode *xattr_item = NULL;
				if (with_values) {
#if defined(__linux__)
					ssize_t rlen2 = getxattr(filename, key, NULL, 0);
#elif defined(__APPLE__)
					ssize_t rlen2 = getxattr(filename, key, NULL, 0, 0, 0);
#endif
					if (rlen > 0) {
						// leave space for final 0
						char *xvalue = uwsgi_calloc(rlen2 + 1);
#if defined(__linux__)
						if (getxattr(filename, key, xvalue, rlen2) > 0) {
#elif defined(__APPLE__)
						if (getxattr(filename, key, xvalue, rlen2, 0 ,0) > 0) {
#endif
							xattr_item = xmlNewTextChild(r_prop, NULL, BAD_CAST xattr_key, BAD_CAST xvalue);
						}
						free(xvalue);	
					}
					else if (rlen == 0) {
						xattr_item = xmlNewTextChild(r_prop, NULL, BAD_CAST xattr_key, NULL);
					}
				}
				else {
					xattr_item = xmlNewTextChild(r_prop, NULL, BAD_CAST xattr_key, NULL);
				}	
				if (separator && xattr_item) {
					xattr_ns = xmlNewNs(xattr_item, BAD_CAST (key + 18), NULL);
					*separator = '|';
					xmlSetNs(xattr_item, xattr_ns);	
				}
			}
			key = NULL;
		}
		else if (key == NULL) {
			key = &xattrs[i];
		}
	}
	free(xattrs);
	
#endif
	return 0;
}

static size_t uwsgi_webdav_expand_path(struct wsgi_request *wsgi_req, char *item, uint16_t item_len, char *filename) {
	struct uwsgi_app *ua = &uwsgi_apps[wsgi_req->app_id];
	char *docroot = ua->interpreter;
	size_t docroot_len = strlen(docroot);

	// merge docroot with path_info
	char *tmp_filename = uwsgi_concat3n(docroot, docroot_len, "/", 1, item, item_len);
	// try expanding the path 
	if (!realpath(tmp_filename, filename)) {
		free(tmp_filename);
		return 0;
	}
	free(tmp_filename);
	return strlen(filename);
}

static size_t uwsgi_webdav_expand_fake_path(struct wsgi_request *wsgi_req, char *item, uint16_t item_len, char *filename) {
	char *last_slash = uwsgi_get_last_charn(item, item_len, '/');
        if (!last_slash) return 0;
        size_t filename_len = uwsgi_webdav_expand_path(wsgi_req, item, last_slash - item, filename);
        if (!filename_len) return 0;
        // check for overflow
        if (filename_len + (item_len - (last_slash - item)) >= PATH_MAX) return 0;
        memcpy(filename + filename_len, last_slash, (item_len - (last_slash - item)));
        filename_len += (item_len - (last_slash - item));
        filename[(int)filename_len] = 0;
	return filename_len;
}

static xmlDoc *uwsgi_webdav_manage_prop(struct wsgi_request *wsgi_req, xmlNode *req_prop, char *filename, size_t filename_len, int with_values) {
	// default 1 depth
	int depth = 1;
        uint16_t http_depth_len = 0;
        char *http_depth = uwsgi_get_var(wsgi_req, "HTTP_DEPTH", 10, &http_depth_len);
        if (http_depth) {
                depth = uwsgi_str_num(http_depth, http_depth_len);
        }

	xmlDoc *rdoc = xmlNewDoc(BAD_CAST "1.0");
        xmlNode *multistatus = xmlNewNode(NULL, BAD_CAST "multistatus");
        xmlDocSetRootElement(rdoc, multistatus);
        xmlNsPtr dav_ns = xmlNewNs(multistatus, BAD_CAST "DAV:", BAD_CAST "D");
        xmlSetNs(multistatus, dav_ns);

	if (depth == 0) {
                char *uri = uwsgi_concat2n(wsgi_req->path_info, wsgi_req->path_info_len, "", 0);
                uwsgi_webdav_add_props(wsgi_req, req_prop, multistatus, dav_ns, uri, filename, with_values);
                free(uri);
        }
        else {
                DIR *collection = opendir(filename);
                struct dirent de;
                for (;;) {
                        struct dirent *de_r = NULL;
                        if (readdir_r(collection, &de, &de_r)) {
                                uwsgi_error("uwsgi_wevdav_manage_propfind()/readdir_r()");
                                break;
                        }
                        if (de_r == NULL) {
                                break;
                        }
                        char *uri = NULL;
                        char *direntry = NULL;
                        if (!strcmp(de.d_name, "..")) {
                                // skip ..
                                continue;
                        }
                        else if (!strcmp(de.d_name, ".")) {
                                uri = uwsgi_concat2n(wsgi_req->path_info, wsgi_req->path_info_len, "", 0);
                                direntry = uwsgi_concat2n(filename, filename_len, "", 0);
                        }
                        else if (wsgi_req->path_info[wsgi_req->path_info_len - 1] == '/') {
                                uri = uwsgi_concat2n(wsgi_req->path_info, wsgi_req->path_info_len, de.d_name, strlen(de.d_name));
                                direntry = uwsgi_concat3n(filename, filename_len, "/", 1, de.d_name, strlen(de.d_name));
                        }
                        else {
                                uri = uwsgi_concat3n(wsgi_req->path_info, wsgi_req->path_info_len, "/", 1, de.d_name, strlen(de.d_name));
                                direntry = uwsgi_concat3n(filename, filename_len, "/", 1, de.d_name, strlen(de.d_name));
                        }
                        uwsgi_webdav_add_props(wsgi_req, req_prop, multistatus, dav_ns, uri, direntry, with_values);
                        free(uri);
                        free(direntry);
                }
                closedir(collection);
        }

	return rdoc;
	
}
Beispiel #19
0
void fastrouter_loop() {

	int nevents;
	int interesting_fd;
	int new_connection;
	ssize_t len;
	int i;

	time_t delta;
	char bbuf[UMAX16];

	char *tcp_port;

	char *tmp_socket_name;
	int tmp_socket_name_len;

	struct uwsgi_subscribe_req usr;

	char *magic_table[0xff];

	struct uwsgi_rb_timer *min_timeout;

	void *events;
	struct msghdr msg;
	union {
                struct cmsghdr cmsg;
                char control [CMSG_SPACE (sizeof (int))];
        } msg_control;
        struct cmsghdr *cmsg;

	struct sockaddr_un fr_addr;
        socklen_t fr_addr_len = sizeof(struct sockaddr_un);
	
	struct fastrouter_session *fr_session;

	struct fastrouter_session *fr_table[2048];

	struct iovec iov[2];

	int soopt;
        socklen_t solen = sizeof(int);

	int ufr_subserver = -1;

	for(i=0;i<2048;i++) {
		fr_table[i] = NULL;
	}

	ufr.queue = event_queue_init();

	struct uwsgi_fastrouter_socket *ufr_sock = ufr.sockets;

	while(ufr_sock) {
		if (ufr_sock->name[0] == '=') {
			int shared_socket = atoi(ufr_sock->name+1);
			if (shared_socket >= 0) {
				ufr_sock->fd = uwsgi_get_shared_socket_fd_by_num(shared_socket);
				if (ufr_sock->fd == -1) {
					uwsgi_log("unable to use shared socket %d\n", shared_socket);
				}
			}
		}
		else {
			tcp_port = strchr(ufr_sock->name, ':');
			if (tcp_port) {
				ufr_sock->fd = bind_to_tcp(ufr_sock->name, uwsgi.listen_queue, tcp_port);
			}
			else {
				ufr_sock->fd = bind_to_unix(ufr_sock->name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
			}
		}

		uwsgi_log("uwsgi fastrouter/proxy bound on %s\n", ufr_sock->name);

		if (!ufr.cheap) {
			event_queue_add_fd_read(ufr.queue, ufr_sock->fd);
		}
		else {
			uwsgi_log("[uwsgi-fastrouter] cheap mode requested. Waiting for subscriptions...\n");
			ufr.i_am_cheap = 1;
		}
		ufr_sock = ufr_sock->next;
	}


	events = event_queue_alloc(ufr.nevents);

	ufr.timeouts = uwsgi_init_rb_timer();
	if (!ufr.socket_timeout) ufr.socket_timeout = 30;


	if (ufr.subscription_server) {
		ufr_subserver = bind_to_udp(ufr.subscription_server, 0, 0);
		event_queue_add_fd_read(ufr.queue, ufr_subserver);
		if (!ufr.subscription_slot) ufr.subscription_slot = 30;
		// check for node status every 10 seconds
		//ufr.subscriptions_check = add_check_timeout(10);
	}

	if (ufr.pattern) {
		init_magic_table(magic_table);
	}


	for (;;) {

		min_timeout = uwsgi_min_rb_timer(ufr.timeouts);
		if (min_timeout == NULL ) {
			delta = -1;
		}
		else {
			delta = min_timeout->key - time(NULL);
			if (delta <= 0) {
				expire_timeouts(fr_table);
				delta = 0;
			}
		}

		nevents = event_queue_wait_multi(ufr.queue, delta, events, ufr.nevents);

		if (nevents == 0) {
			expire_timeouts(fr_table);
		}

		for (i=0;i<nevents;i++) {

			tmp_socket_name = NULL;
			interesting_fd = event_queue_interesting_fd(events, i);


			int taken = 0;
			struct uwsgi_fastrouter_socket *uwsgi_sock = ufr.sockets;
			while(uwsgi_sock) {
				if (interesting_fd == uwsgi_sock->fd) {
					new_connection = accept(interesting_fd, (struct sockaddr *) &fr_addr, &fr_addr_len);
					if (new_connection < 0) {
						continue;
					}

					fr_table[new_connection] = alloc_fr_session();
					fr_table[new_connection]->fd = new_connection;
					fr_table[new_connection]->instance_fd = -1; 
					fr_table[new_connection]->status = FASTROUTER_STATUS_RECV_HDR;
					fr_table[new_connection]->h_pos = 0;
					fr_table[new_connection]->pos = 0;
					fr_table[new_connection]->un = NULL;
					fr_table[new_connection]->instance_failed = 0;
					fr_table[new_connection]->instance_address_len = 0;
					fr_table[new_connection]->hostname_len = 0;
					fr_table[new_connection]->hostname = NULL;
		
					fr_table[new_connection]->timeout = add_timeout(fr_table[new_connection]);

					event_queue_add_fd_read(ufr.queue, new_connection);
					taken = 1;
					break;
				}
				
				uwsgi_sock = uwsgi_sock->next;
			}	

			if (taken) {
				continue;
			}

			if (interesting_fd == ufr_subserver) {
				len = recv(ufr_subserver, bbuf, 4096, 0);
#ifdef UWSGI_EVENT_USE_PORT
				event_queue_add_fd_read(ufr.queue, ufr_subserver);
#endif
				if (len > 0) {
					memset(&usr, 0, sizeof(struct uwsgi_subscribe_req));
					uwsgi_hooked_parse(bbuf+4, len-4, fastrouter_manage_subscription, &usr);
					if (uwsgi_add_subscribe_node(&ufr.subscriptions, &usr, ufr.subscription_regexp) && ufr.i_am_cheap) {
						struct uwsgi_fastrouter_socket *ufr_sock = ufr.sockets;
                                                while(ufr_sock) {
                                                	event_queue_add_fd_read(ufr.queue, ufr_sock->fd);
                                                        ufr_sock = ufr_sock->next;
                                                }
						ufr.i_am_cheap = 0;
						uwsgi_log("[uwsgi-fastrouter] leaving cheap mode...\n");	
					}
				}
			}
			else {
				fr_session = fr_table[interesting_fd];

				// something is going wrong...
				if (fr_session == NULL) continue;

				if (event_queue_interesting_fd_has_error(events, i)) {
					close_session(fr_table, fr_session);
					continue;
				}

				fr_session->timeout = reset_timeout(fr_session);

				switch(fr_session->status) {

					case FASTROUTER_STATUS_RECV_HDR:
						len = recv(fr_session->fd, (char *)(&fr_session->uh) + fr_session->h_pos, 4-fr_session->h_pos, 0);
						if (len <= 0) {
							uwsgi_error("recv()");
							close_session(fr_table, fr_session);
							break;
						}
						fr_session->h_pos += len;
						if (fr_session->h_pos == 4) {
#ifdef UWSGI_DEBUG
							uwsgi_log("modifier1: %d pktsize: %d modifier2: %d\n", fr_session->uh.modifier1, fr_session->uh.pktsize, fr_session->uh.modifier2);
#endif
							fr_session->status = FASTROUTER_STATUS_RECV_VARS;
						}
						break;


					case FASTROUTER_STATUS_RECV_VARS:
                                                len = recv(fr_session->fd, fr_session->buffer + fr_session->pos, fr_session->uh.pktsize - fr_session->pos, 0);
                                                if (len <= 0) {
                                                        uwsgi_error("recv()");
							close_session(fr_table, fr_session);
                                                        break;
                                                }
                                                fr_session->pos += len;
                                                if (fr_session->pos == fr_session->uh.pktsize) {
							if (uwsgi_hooked_parse(fr_session->buffer, fr_session->uh.pktsize, fr_get_hostname, (void *) fr_session)) {
								close_session(fr_table, fr_session);
                                                        	break;
							}

							if (fr_session->hostname_len == 0) {
								close_session(fr_table, fr_session);
                                                        	break;
							}

#ifdef UWSGI_DEBUG
							//uwsgi_log("requested domain %.*s\n", fr_session->hostname_len, fr_session->hostname);
#endif
							if (ufr.use_cache) {
								fr_session->instance_address = uwsgi_cache_get(fr_session->hostname, fr_session->hostname_len, &fr_session->instance_address_len);
								char *cs_mod = uwsgi_str_contains(fr_session->instance_address, fr_session->instance_address_len, ',');
                                                                if (cs_mod) {
                                                                	fr_session->modifier1 = uwsgi_str_num(cs_mod+1, (fr_session->instance_address_len - (cs_mod - fr_session->instance_address))-1);
                                                                        fr_session->instance_address_len = (cs_mod - fr_session->instance_address);
                                                                }
							}
							else if (ufr.pattern) {
								magic_table['s'] = uwsgi_concat2n(fr_session->hostname, fr_session->hostname_len, "", 0);	
								tmp_socket_name = magic_sub(ufr.pattern, ufr.pattern_len, &tmp_socket_name_len, magic_table);
								free(magic_table['s']);
								fr_session->instance_address_len = tmp_socket_name_len;
								fr_session->instance_address = tmp_socket_name;
							}
							else if (ufr.subscription_server) {
								fr_session->un = uwsgi_get_subscribe_node(&ufr.subscriptions, fr_session->hostname, fr_session->hostname_len, ufr.subscription_regexp);
								if (fr_session->un && fr_session->un->len) {
									fr_session->instance_address = fr_session->un->name;
									fr_session->instance_address_len = fr_session->un->len;
									fr_session->modifier1 = fr_session->un->modifier1;
								}
							}
							else if (ufr.base) {
								tmp_socket_name = uwsgi_concat2nn(ufr.base, ufr.base_len, fr_session->hostname, fr_session->hostname_len, &tmp_socket_name_len);
								fr_session->instance_address_len = tmp_socket_name_len;
								fr_session->instance_address = tmp_socket_name;
							}
							else if (ufr.code_string_code && ufr.code_string_function) {
								if (uwsgi.p[ufr.code_string_modifier1]->code_string) {
									fr_session->instance_address = uwsgi.p[ufr.code_string_modifier1]->code_string("uwsgi_fastrouter", ufr.code_string_code, ufr.code_string_function, fr_session->hostname, fr_session->hostname_len);
									if (fr_session->instance_address) {
										fr_session->instance_address_len = strlen(fr_session->instance_address);
										char *cs_mod = uwsgi_str_contains(fr_session->instance_address, fr_session->instance_address_len, ',');
										if (cs_mod) {
											fr_session->modifier1 = uwsgi_str_num(cs_mod+1, (fr_session->instance_address_len - (cs_mod - fr_session->instance_address))-1);
											fr_session->instance_address_len = (cs_mod - fr_session->instance_address);
										}
									}
								}
							}

							// no address found
							if (!fr_session->instance_address_len) {
								close_session(fr_table, fr_session);
                                                        	break;
							}


							fr_session->pass_fd = is_unix(fr_session->instance_address, fr_session->instance_address_len);

							fr_session->instance_fd = uwsgi_connectn(fr_session->instance_address, fr_session->instance_address_len, 0, 1);

							if (tmp_socket_name) free(tmp_socket_name);

							if (fr_session->instance_fd < 0) {
								/*
								if (ufr.subscription_server) {
									if (fr_session->un && fr_session->un->len > 0) { 
	                                                        		uwsgi_log("[uwsgi-fastrouter] %.*s => marking %.*s as failed\n", (int) fr_session->hostname_len, fr_session->hostname, (int) fr_session->instance_address_len,fr_session->instance_address);
                                						uwsgi_remove_subscribe_node(&ufr.subscriptions, fr_session->un);	 
										if (ufr.subscriptions == NULL && ufr.cheap && !ufr.i_am_cheap) {
											uwsgi_log("[uwsgi-fastrouter] no more nodes available. Going cheap...\n");
											struct uwsgi_fastrouter_socket *ufr_sock = ufr.sockets;	
											while(ufr_sock) {
												event_queue_del_fd(ufr.queue, ufr_sock->fd, event_queue_read());	
												ufr_sock = ufr_sock->next;
											}
											ufr.i_am_cheap = 1;
										}
                        						}
	                                                        }
								*/
								fr_session->instance_failed = 1;
								close_session(fr_table, fr_session);
                                                        	break;
							}


							fr_session->status = FASTROUTER_STATUS_CONNECTING;
							fr_table[fr_session->instance_fd] = fr_session;
							event_queue_add_fd_write(ufr.queue, fr_session->instance_fd);
                                                }
                                                break;



					case FASTROUTER_STATUS_CONNECTING:
						
						if (interesting_fd == fr_session->instance_fd) {

							if (getsockopt(fr_session->instance_fd, SOL_SOCKET, SO_ERROR, (void *) (&soopt), &solen) < 0) {
                                                		uwsgi_error("getsockopt()");
								fr_session->instance_failed = 1;
								close_session(fr_table, fr_session);
                                                        	break;
                                        		}

							if (soopt) {
								uwsgi_log("unable to connect() to uwsgi instance: %s\n", strerror(soopt));
								fr_session->instance_failed = 1;
								close_session(fr_table, fr_session);
                                                        	break;
							}

							fr_session->uh.modifier1 = fr_session->modifier1;

							iov[0].iov_base = &fr_session->uh;
							iov[0].iov_len = 4;
							iov[1].iov_base = fr_session->buffer;
							iov[1].iov_len = fr_session->uh.pktsize;

							// increment node requests counter
							if (fr_session->un)
								fr_session->un->requests++;

							// fd passing: PERFORMANCE EXTREME BOOST !!!
							if (fr_session->pass_fd && !uwsgi.no_fd_passing) {
								msg.msg_name    = NULL;
                						msg.msg_namelen = 0;
                						msg.msg_iov     = iov;
                						msg.msg_iovlen  = 2;
                						msg.msg_flags   = 0;
                						msg.msg_control    = &msg_control;
                						msg.msg_controllen = sizeof (msg_control);

                						cmsg = CMSG_FIRSTHDR (&msg);
                						cmsg->cmsg_len   = CMSG_LEN (sizeof (int));
                						cmsg->cmsg_level = SOL_SOCKET;
                						cmsg->cmsg_type  = SCM_RIGHTS;

								memcpy(CMSG_DATA(cmsg), &fr_session->fd, sizeof(int));

                						if (sendmsg(fr_session->instance_fd, &msg, 0) < 0) {
									uwsgi_error("sendmsg()");
								}

								close_session(fr_table, fr_session);	
                                                                break;
							}

							if (writev(fr_session->instance_fd, iov, 2) < 0) {
								uwsgi_error("writev()");
								close_session(fr_table, fr_session);
                                                        	break;
							}

							event_queue_fd_write_to_read(ufr.queue, fr_session->instance_fd);
							fr_session->status = FASTROUTER_STATUS_RESPONSE;
						}

						break;

					case FASTROUTER_STATUS_RESPONSE:
						
						// data from instance
						if (interesting_fd == fr_session->instance_fd) {
							len = recv(fr_session->instance_fd, fr_session->buffer, 0xffff, 0);
							if (len <= 0) {
								if (len < 0) uwsgi_error("recv()");
								close_session(fr_table, fr_session);
                                                        	break;
							}

							len = send(fr_session->fd, fr_session->buffer, len, 0);
							
							if (len <= 0) {
								if (len < 0) uwsgi_error("send()");
								close_session(fr_table, fr_session);
                                                        	break;
							}

							// update transfer statistics
							if (fr_session->un)
								fr_session->un->transferred += len;
						}
						// body from client
						else if (interesting_fd == fr_session->fd) {

							//uwsgi_log("receiving body...\n");
							len = recv(fr_session->fd, fr_session->buffer, 0xffff, 0);
							if (len <= 0) {
								if (len < 0) uwsgi_error("recv()");
								close_session(fr_table, fr_session);
                                                        	break;
							}


							len = send(fr_session->instance_fd, fr_session->buffer, len, 0);
							
							if (len <= 0) {
								if (len < 0) uwsgi_error("send()");
								close_session(fr_table, fr_session);
                                                        	break;
							}
						}

						break;



					// fallback to destroy !!!
					default:
						uwsgi_log("unknown event: closing session\n");
						close_session(fr_table, fr_session);
						break;
					
				}
			}

		}
	}
}
Beispiel #20
0
void uwsgi_map_sockets() {
	struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
	while (uwsgi_sock) {
		struct uwsgi_string_list *usl = uwsgi.map_socket;
		int enabled = 1;
		while (usl) {

			char *colon = strchr(usl->value, ':');
			if (!colon) {
				uwsgi_log("invalid socket mapping, must be socket:worker[,worker...]\n");
				exit(1);
			}
			if ((int) uwsgi_str_num(usl->value, colon - usl->value) == uwsgi_get_socket_num(uwsgi_sock)) {
				enabled = 0;
				char *p = strtok(colon + 1, ",");
				while (p != NULL) {
					int w = atoi(p);
					if (w < 1 || w > uwsgi.numproc) {
						uwsgi_log("invalid worker num: %d\n", w);
						exit(1);
					}
					if (w == uwsgi.mywid) {
						enabled = 1;
						uwsgi_log("mapped socket %d (%s) to worker %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi.mywid);
						break;
					}
					p = strtok(NULL, ",");
				}
			}

			usl = usl->next;
		}

		if (!enabled) {
			close(uwsgi_sock->fd);
			int fd = open("/dev/null", O_RDONLY);
			if (fd < 0) {
				uwsgi_error_open("/dev/null");
				exit(1);
			}
			if (fd != uwsgi_sock->fd) {
				if (dup2(fd, uwsgi_sock->fd) < 0) {
					uwsgi_error("dup2()");
					exit(1);
				}
				close(fd);
			}
			uwsgi_sock->disabled = 1;
		}


		uwsgi_sock = uwsgi_sock->next;

	}

	uwsgi_sock = uwsgi.sockets;
	while (uwsgi_sock) {
		if (uwsgi_sock->disabled) {
			uwsgi_sock = uwsgi_del_socket(uwsgi_sock);
		}
		else {
			uwsgi_sock = uwsgi_sock->next;
		}
	}

}
Beispiel #21
0
static void uwsgi_rados_propfind(struct wsgi_request *wsgi_req, rados_ioctx_t ctx, char *key, uint64_t size, time_t mtime, int timeout) {
	// consume the body
	size_t remains = wsgi_req->post_cl;
        while(remains > 0) {
                ssize_t body_len = 0;
                char *body =  uwsgi_request_body_read(wsgi_req, UMIN(remains, 32768), &body_len);
                if (!body || body == uwsgi.empty) break;
		remains -= body_len;
	}

	if (uwsgi_response_prepare_headers(wsgi_req, "207 Multi-Status", 16)) return;
	if (uwsgi_response_add_content_type(wsgi_req, "text/xml; charset=\"utf-8\"", 25)) return;
	struct uwsgi_buffer *ub = uwsgi_webdav_multistatus_new();
	if (!ub) return;
	if (key) {
		size_t mime_type_len = 0;
        	char *mime_type = uwsgi_get_mime_type(key, strlen(key), &mime_type_len);
		char *slashed = uwsgi_concat2("/", key);
		if (uwsgi_webdav_propfind_item_add(ub, slashed, strlen(key)+1, size, mtime, mime_type, mime_type_len, NULL, 0, NULL, 0)) {
			free(slashed);
			goto end;
		}
		free(slashed);
		if (uwsgi_webdav_multistatus_close(ub)) goto end;
		uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
		goto end;
	}
	// request for /
	size_t depth = 0;
	uint16_t http_depth_len = 0;
        char *http_depth = uwsgi_get_var(wsgi_req, "HTTP_DEPTH", 10, &http_depth_len);
        if (http_depth) {
                depth = uwsgi_str_num(http_depth, http_depth_len);
        }

	if (depth == 0) {
		if (uwsgi_webdav_propfind_item_add(ub, "/", 1, 0, 0, NULL, 0, NULL, 0, NULL, 0)) {
                        goto end;
                }
                if (uwsgi_webdav_multistatus_close(ub)) goto end;
                uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
		goto end;
	}

	struct uwsgi_rados_io *urio = &urados.urio[wsgi_req->async_id];
	rados_list_ctx_t ctx_list;
	if (rados_objects_list_open(ctx, &ctx_list) < 0) {
		goto end;
	}

	char *entry = NULL;
	while(rados_objects_list_next(ctx_list, (const char **)&entry, NULL) == 0) {
		uint64_t stat_size = 0;
		time_t stat_mtime = 0;
		if (uwsgi.async > 0) {
        		if (uwsgi_rados_async_stat(urio, ctx, entry, &stat_size, &stat_mtime, timeout) < 0) goto end;
        	}
        	else {
                	if (rados_stat(ctx, entry, &stat_size, &stat_mtime) < 0) goto end;
        	}

		size_t mime_type_len = 0;
                char *mime_type = uwsgi_get_mime_type(entry, strlen(entry), &mime_type_len);
                char *slashed = uwsgi_concat2("/", entry);
                if (uwsgi_webdav_propfind_item_add(ub, slashed, strlen(entry)+1, stat_size, stat_mtime, mime_type, mime_type_len, NULL, 0, NULL, 0)) {
                        free(slashed);
                        goto end;
                }
                free(slashed);
                if (uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos)) goto end;
		// reset buffer;
		ub->pos = 0;
	}
	rados_objects_list_close(ctx_list);
        if (uwsgi_webdav_multistatus_close(ub)) goto end;
        uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);

end:
	uwsgi_buffer_destroy(ub);
}