Пример #1
0
static yar_response * yar_client_caller(yar_client *client, char *method, uint num_args, yar_packager *parameters[]) /* {{{ */ {
	int	bytes_sent, select_result;
	uint bytes_left, totolly_read;
	yar_header *response_header = NULL;
	yar_response *response;
	yar_request  *request;
	yar_header header = {0};
	yar_payload payload = {0};
	struct timeval tv;
	fd_set readfds, writefds;

	if (client->timeout){
		tv.tv_sec = client->timeout;
	} else {
		tv.tv_sec = 1; /* default 1 second */
	}
	tv.tv_usec = 0; 

	request = calloc(1, sizeof(yar_request));
	request->id = 1000; /* dummy id */
	request->method = strdup(method);
	request->mlen = strlen(method);
	if (num_args) {
		uint i;
		yar_packager *packager = yar_pack_start_array(num_args);
		for (i=0;i<num_args;i++) {
			yar_pack_push_packager(packager, parameters[i]);
		}
		yar_request_set_parameters(request, packager);
		yar_pack_free(packager);
	}

	if (!yar_request_pack(request, &payload, sizeof(yar_header) + sizeof(YAR_PACKAGER))) {
		alog(YAR_ERROR, "Packing request failed");
		yar_request_free(request);
		free(request);
		return NULL;
	}

	yar_protocol_render(&header, request->id, YAR_CLIENT_NAME, NULL, payload.size - sizeof(yar_header), client->persistent? YAR_PROTOCOL_PERSISTENT : 0);

	memcpy(payload.data, (char *)&header, sizeof(yar_header));
	memcpy(payload.data + sizeof(yar_header), YAR_PACKAGER, sizeof(YAR_PACKAGER));
	yar_request_free(request);
	free(request);

	FD_ZERO(&writefds);
	FD_SET(client->fd, &writefds);

	bytes_left = payload.size;

write_wait:
	if ((select_result = select(client->fd + 1, NULL, &writefds, NULL, &tv)) == 0) {
		alog(YAR_ERROR, "Select for client timeout '%s'", strerror(errno));
		free(payload.data);
		return NULL;
	} else if (select == -1) {
		alog(YAR_ERROR, "Select for client failed '%s'", strerror(errno));
		free(payload.data);
		return NULL;
	}

	if (!FD_ISSET(client->fd, &writefds)) {
		goto write_wait;
	} else {
		do {
			bytes_sent = send(client->fd, payload.data + payload.size - bytes_left, bytes_left, 0);
		} while (bytes_sent == -1 && errno == EINTR);

		if (bytes_sent < 0) {
			alog(YAR_ERROR, "Send request failed", strerror(errno));
			free(payload.data);
			return NULL;
		}

		bytes_left -= bytes_sent;
		if (bytes_left) {
			goto write_wait;
		}
	} 

	free(payload.data);

	FD_ZERO(&readfds);
	FD_SET(client->fd, &readfds);

	response = calloc(1, sizeof(yar_response));
	totolly_read = 0;

read_wait:
	if ((select_result = select(client->fd + 1, &readfds, NULL, NULL, &tv)) == 0) {
		alog(YAR_ERROR, "Select for client timeout '%s'", strerror(errno));
		yar_response_free(response);
		free(response);
		return NULL;
	} else  if (select_result == -1) {
		alog(YAR_ERROR, "Select for client failed '%s'", strerror(errno));
		yar_response_free(response);
		free(response);
		return NULL;
	}

	if (!FD_ISSET(client->fd, &readfds)) {
		goto read_wait;
	} else {
		int bytes_read = 0;
		if (!response_header) {
			char buf[sizeof(yar_header)];
			do {
				bytes_read = recv(client->fd, buf, sizeof(buf), 0);
			} while (bytes_read == -1 && errno == EINTR);

			if (bytes_read == 0) {
				alog(YAR_ERROR, "Server closed connection prematurely");
				yar_response_free(response);
				free(response);
				return NULL;
			} else if (bytes_read < 0) {
				alog(YAR_ERROR, "Failed read response '%s'", strerror(errno));
				yar_response_free(response);
				free(response);
				return NULL;
			}

			response_header = (yar_header *)buf;
			if (!yar_protocol_parse(response_header)) {
				alog(YAR_ERROR, "Parsing response header failed, maybe not responsed by a rpc server?");
				yar_response_free(response);
				free(response);
				return NULL;
			}
			if (!response->payload.data) {
				response->payload.data = malloc(sizeof(yar_header) + response_header->body_len);
				response->payload.size = sizeof(yar_header) + response_header->body_len;
			}
			memcpy(response->payload.data + totolly_read, buf, bytes_read);
			totolly_read += bytes_read;
		}

		do {
			bytes_read = recv(client->fd, response->payload.data + bytes_read, response->payload.size - bytes_read, 0);
		} while (bytes_read == -1 && errno == EINTR);

		if (bytes_read == 0) {
			alog(YAR_ERROR, "Lost connection to server");
			yar_response_free(response);
			free(response);
			return NULL;
		} else if (bytes_read < 0) {
			alog(YAR_ERROR, "Failed read response '%s'", strerror(errno));
			yar_response_free(response);
			free(response);
			return NULL;
		}

		totolly_read += bytes_read;
		if (totolly_read < response_header->body_len + sizeof(yar_header)) {
			goto read_wait;
		}

		if (!yar_response_unpack(response, response->payload.data, response->payload.size, sizeof(yar_header) + sizeof(YAR_PACKAGER))) {
			alog(YAR_ERROR, "Unpack response failed");
			yar_response_free(response);
			free(response);
			return NULL;
		}

		return response;
	}

}
void ngx_http_yar_handler(ngx_http_request_t *r){

    ngx_str_t error;

    ngx_str_t *client_request_body = ngx_http_yar_read_client_post_body(r);

    yar_request *request = NULL;

    yar_response *response = NULL;



    if(!client_request_body || client_request_body->len < sizeof(yar_header)){

        ngx_str_set(&error,"read request body error.");

        goto send_error;

    }

    request = ngx_http_yar_get_yar_request(r,client_request_body);

    if(!request){

        ngx_str_set(&error,"parse yar protocol error.");

        goto send_error;

    }

    if(request->mlen < 1){

        ngx_str_set(&error,"call undefined method.");

        goto send_error;

    }

    response = ngx_http_yar_get_yar_response(r,request);

    if(!response){

        ngx_str_set(&error,"get response error.");

        goto send_error;

    }

    if (!yar_response_pack(response, &(response->payload), sizeof(yar_header) + sizeof(YAR_PACKAGER))) {

        ngx_str_set(&error,"protocol pack response error.");

        goto send_error;

    }


    yar_header response_header;

    yar_protocol_render(&response_header, request->id, NULL, NULL, response->payload.size - sizeof(yar_header), 0);

    memcpy(response->payload.data, (char *)&response_header, sizeof(yar_header));

    memcpy(response->payload.data + sizeof(yar_header), YAR_PACKAGER, sizeof(YAR_PACKAGER));

    ngx_str_t *reply = ngx_pcalloc (r->pool, sizeof (ngx_str_t));

    u_char *data  = ngx_pcalloc (r->pool, sizeof (u_char) * response->payload.size);

    reply->len = response->payload.size;

    memcpy(data,response->payload.data,response->payload.size);

    reply->data = data;

    ngx_http_yar_send_response(r,reply);

    goto clean_resource;

    while(0){

        send_error:
        {

            ngx_http_yar_send_response (r, &error);

            goto clean_resource;
        };

        return ;

    }

    clean_resource:
    {
        if (request) {

            yar_request_free (request);

        }

        if (response) {

            yar_response_free (response);

        }
    }

}
Пример #3
0
static yar_response * yar_client_caller(yar_client *client, char *method, uint num_args, yar_packager *parameters[]) /* {{{ */ {
	int	bytes_sent, select_result;
	uint bytes_left, totolly_read;
	yar_header *response_header = NULL;
	yar_response *response;
	yar_request  *request;
	yar_header header = {0};
	yar_payload payload = {0};
	fd_set readfds, writefds;
	struct timeval tv = {.tv_sec = 1, .tv_usec = 0};

	request = calloc(1, sizeof(yar_request));
	request->id = 1000; /* dummy id */
	request->method = strdup(method);
	request->mlen = strlen(method);
	if (num_args) {
		uint i;
		yar_packager *packager = yar_pack_start_array(num_args);
		for (i=0;i<num_args;i++) {
			yar_pack_push_packager(packager, parameters[i]);
		}
		yar_request_set_parameters(request, packager);
		yar_pack_free(packager);
	}

	if (!yar_request_pack(request, &payload, sizeof(yar_header) + sizeof(YAR_PACKAGER))) {
		alog(YAR_ERROR, "Packing request failed");
		yar_request_free(request);
		free(request);
		return NULL;
	}

	yar_protocol_render(&header, request->id, YAR_CLIENT_NAME, NULL, payload.size - sizeof(yar_header), client->persistent? YAR_PROTOCOL_PERSISTENT : 0);

	memcpy(payload.data, (char *)&header, sizeof(yar_header));
	memcpy(payload.data + sizeof(yar_header), YAR_PACKAGER, sizeof(YAR_PACKAGER));
	yar_request_free(request);
	free(request);

	FD_ZERO(&writefds);
	FD_SET(client->fd, &writefds);

	bytes_left = payload.size;

write_wait:
	while ((select_result = select(client->fd + 1, NULL, &writefds, NULL, &tv)) == 0);
	if (select_result == -1) {
		alog(YAR_ERROR, "Select for client fd failed '%s'", strerror(errno));
		free(payload.data);
		return NULL;
	} 

	if (!FD_ISSET(client->fd, &writefds)) {
		goto write_wait;
	} else {
		do {
			bytes_sent = send(client->fd, payload.data + payload.size - bytes_left, bytes_left, 0);
		} while (bytes_sent == -1 && errno == EINTR);

		if (bytes_sent < 0) {
			alog(YAR_ERROR, "Send request failed", strerror(errno));
			free(payload.data);
			return NULL;
		}

		bytes_left -= bytes_sent;
		if (bytes_left) {
			goto write_wait;
		}
	} 

	free(payload.data);

	FD_ZERO(&readfds);
	FD_SET(client->fd, &readfds);

	response = calloc(1, sizeof(yar_response));
	totolly_read = 0;

read_wait:
	while ((select_result = select(client->fd + 1, &readfds, NULL, NULL, &tv)) == 0);
	if (select_result == -1) {
		alog(YAR_ERROR, "Select for client fd failed '%s'", strerror(errno));
		free(payload.data);
		yar_response_free(response);
		free(response);
		return NULL;
	} 

	if (!FD_ISSET(client->fd, &readfds)) {
		goto read_wait;
	} else {
		int bytes_read = 0;
		if (!response_header) {
			char buf[sizeof(yar_header)];
			do {
				bytes_read = recv(client->fd, buf, sizeof(buf), 0);
			} while (bytes_read == -1 && errno == EINTR);

			if (bytes_read == 0) {
				alog(YAR_ERROR, "Server closed connection prematurely");
				yar_response_free(response);
				free(response);
				return NULL;
			} else if (bytes_read < 0) {
				alog(YAR_ERROR, "Failed read response '%s'", strerror(errno));
				yar_response_free(response);
				free(response);
				return NULL;
			}

			response_header = (yar_header *)buf;
			if (!yar_protocol_parse(response_header)) {
				alog(YAR_ERROR, "Parsing response header failed, maybe not responsed by a rpc server?");
				yar_response_free(response);
				free(response);
				return NULL;
			}
			if (!response->payload.data) {
				response->payload.data = malloc(sizeof(yar_header) + response_header->body_len);
				response->payload.size = sizeof(yar_header) + response_header->body_len;
			}
			memcpy(response->payload.data + totolly_read, buf, bytes_read);
			totolly_read += bytes_read;
		}

		do {
			bytes_read = recv(client->fd, response->payload.data + bytes_read, response->payload.size - bytes_read, 0);
		} while (bytes_read == -1 && errno == EINTR);

		if (bytes_read == 0) {
			alog(YAR_ERROR, "Lost connection to server");
			yar_response_free(response);
			free(response);
			return NULL;
		} else if (bytes_read < 0) {
			alog(YAR_ERROR, "Failed read response '%s'", strerror(errno));
			yar_response_free(response);
			free(response);
			return NULL;
		}

		totolly_read += bytes_read;
		if (totolly_read < response_header->body_len + sizeof(yar_header)) {
			goto read_wait;
		}

		if (!yar_response_unpack(response, response->payload.data, response->payload.size, sizeof(yar_header) + sizeof(YAR_PACKAGER))) {
			alog(YAR_ERROR, "Unpack response failed");
			yar_response_free(response);
			free(response);
			return NULL;
		}

		return response;
	}

}
/* }}} */

yar_client * yar_client_init(char *hostname) /* {{{ */ {
	struct sockaddr sa;
	int sockfd;
	yar_client *client = calloc(1, sizeof(yar_client));

	client->hostname = hostname;
	client->call = yar_client_caller;

	if (strncasecmp(hostname, "http://", sizeof("http://")) == 0
			|| strncasecmp(hostname, "https://", sizeof("https://")) == 0) {
		/* libcurl */
		free(client);
		return NULL;
	} else if (hostname[0] == '/') {
		/* unix domain socket */
		struct sockaddr_un *usa;
		usa = (struct sockaddr_un *)&sa;
		if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0) == -1)) {
			alog(YAR_ERROR, "Failed to create a socket '%s'", strerror(errno));
			free(client);
			return NULL;
		}
		usa->sun_family = AF_UNIX;
		memcpy(usa->sun_path, hostname, strlen(hostname) + 1);
	} else {
		/* IPV4, we don't support IPV6 for now */
		char *delim, *p, host[1024];
		int port;
		struct hostent *hptr;
		struct sockaddr_in *isa;
		if ((delim = strchr(hostname, ':'))) {
			memcpy(host, hostname, delim - hostname);
			host[delim - hostname] = '\0';
			port = atoi(delim + 1);
		} else {
			alog(YAR_ERROR, "Port doesn't specificed");
			free(client);
			return NULL;
		}

		if ((hptr = gethostbyname(host)) == NULL) {
			alog(YAR_ERROR, "Failed to resolve host name '%s'", strerror(errno));
			free(client);
			return NULL;
		}

		p = hptr->h_addr;
		if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
			alog(YAR_ERROR, "Failed to create a socket '%s'", strerror(errno));
			free(client);
			return NULL;
		}

		switch (hptr->h_addrtype) {
			case AF_INET:
				{
					int val = 1;
					isa = (struct sockaddr_in *)&sa;
					bzero(isa, sizeof(struct sockaddr_in));

					isa->sin_family = AF_INET;
					isa->sin_port = htons(port);
					memcpy(&isa->sin_addr, p, sizeof(struct in_addr));

					setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char*)&val, sizeof(val));
				}
				break;
			default:
				alog(YAR_ERROR, "Unknown address type %d", hptr->h_addrtype);
				close(sockfd);
				free(client);
				return NULL;
		}
	}

	if (connect(sockfd, (const struct sockaddr *)&sa, sizeof(sa)) == -1) {
		alog(YAR_ERROR, "Failed to connect to host '%s'", strerror(errno));
		close(sockfd);
		free(client);
		return NULL;
	}

	yar_set_non_blocking(sockfd);

	client->fd = sockfd;

	return client;
}
/* }}} */

int yar_client_set_opt(yar_client *client, yar_client_opt opt, void *val) /* {{{ */ {
	switch (opt) {
		case YAR_PERSISTENT_LINK:
			client->persistent = *(int *)val;
		break;
		default:
			return 0;
	}
	return 1;
}
/* }}} */

const void * yar_client_get_opt(yar_client *client, yar_client_opt opt) /* {{{ */ {
	switch (opt) {
		case YAR_PERSISTENT_LINK:
			return &client->persistent;
		break;
		default:
			return NULL;
	}
}