Exemplo n.º 1
0
int
as_msg_send_reply(as_file_handle *fd_h, uint32_t result_code, uint32_t generation,
		uint32_t void_time, as_msg_op **ops, as_bin **bins, uint16_t bin_count,
		as_namespace *ns, uint *written_sz, uint64_t trid, const char *setname)
{
	int rv = 0;

	// most cases are small messages - try to stack alloc if we can
	byte fb[MSG_STACK_BUFFER_SZ];
	size_t msg_sz = sizeof(fb);
//	memset(fb,0xff,msg_sz);  // helpful to see what you might not be setting

	uint8_t *msgp = (uint8_t *) as_msg_make_response_msg( result_code, generation,
					void_time, ops, bins, bin_count, ns,
					(cl_msg *)fb, &msg_sz, trid, setname);

	if (!msgp)	return(-1);

	if (fd_h->fd == 0) {
		cf_warning(AS_PROTO, "write to fd 0 internal error");
		cf_crash(AS_PROTO, "send reply: can't write to fd 0");
	}

//	cf_detail(AS_PROTO, "write fd %d",fd);

	size_t pos = 0;
	while (pos < msg_sz) {
		int rv = send(fd_h->fd, msgp + pos, msg_sz - pos, MSG_NOSIGNAL);
		if (rv > 0) {
			pos += rv;
		}
		else if (rv < 0) {
			if (errno != EWOULDBLOCK) {
				// common message when a client aborts
				cf_debug(AS_PROTO, "protocol write fail: fd %d sz %zd pos %zd rv %d errno %d", fd_h->fd, msg_sz, pos, rv, errno);
				as_end_of_transaction_force_close(fd_h);
				rv = -1;
				goto Exit;
			}
			usleep(1); // Yield
		} else {
			cf_info(AS_PROTO, "protocol write fail zero return: fd %d sz %d pos %d ", fd_h->fd, msg_sz, pos);
			as_end_of_transaction_force_close(fd_h);
			rv = -1;
			goto Exit;
		}
	}

	// good for stats as a higher layer
	if (written_sz) *written_sz = msg_sz;

	as_end_of_transaction_ok(fd_h);

Exit:
	if ((uint8_t *)msgp != fb)
		cf_free(msgp);

	return(rv);
}
Exemplo n.º 2
0
// Security is an enterprise feature. If we receive a security message from a
// client here, quickly return AS_SEC_ERR_NOT_SUPPORTED. The client may choose
// to continue using this (unsecured) socket.
void
as_security_transact(as_transaction* tr)
{
	// We don't need the request, since we're ignoring it.
	cf_free(tr->msgp);
	tr->msgp = NULL;

	// Set up a simple response with a single as_sec_msg that has no fields.
	size_t resp_size = sizeof(as_proto) + sizeof(as_sec_msg);
	uint8_t resp[resp_size];

	// Fill out the as_proto fields.
	as_proto* p_resp_proto = (as_proto*)resp;

	p_resp_proto->version = PROTO_VERSION;
	p_resp_proto->type = PROTO_TYPE_SECURITY;
	p_resp_proto->sz = sizeof(as_sec_msg);

	// Switch to network byte order.
	as_proto_swap(p_resp_proto);

	uint8_t* p_proto_body = resp + sizeof(as_proto);

	memset((void*)p_proto_body, 0, sizeof(as_sec_msg));

	// Fill out the relevant as_sec_msg fields.
	as_sec_msg* p_sec_msg = (as_sec_msg*)p_proto_body;

	p_sec_msg->scheme = AS_SEC_MSG_SCHEME;
	p_sec_msg->result = AS_SEC_ERR_NOT_SUPPORTED;

	// Send the complete response.
	cf_socket *sock = &tr->from.proto_fd_h->sock;

	if (cf_socket_send_all(sock, resp, resp_size, MSG_NOSIGNAL,
			CF_SOCKET_TIMEOUT) < 0) {
		cf_warning(AS_SECURITY, "fd %d send failed, errno %d",
				CSFD(sock), errno);
		as_end_of_transaction_force_close(tr->from.proto_fd_h);
		tr->from.proto_fd_h = NULL;
		return;
	}

	as_end_of_transaction_ok(tr->from.proto_fd_h);
	tr->from.proto_fd_h = NULL;
}
Exemplo n.º 3
0
// Send a response made by write_local().
// TODO - refactor and share with as_msg_send_reply().
int
as_msg_send_ops_reply(as_file_handle *fd_h, cf_dyn_buf *db)
{
	int rv = 0;

	if (fd_h->fd == 0) {
		cf_crash(AS_PROTO, "fd is 0");
	}

	uint8_t *msgp = db->buf;
	size_t msg_sz = db->used_sz;
	size_t pos = 0;

	while (pos < msg_sz) {
		int result = send(fd_h->fd, msgp + pos, msg_sz - pos, MSG_NOSIGNAL);

		if (result > 0) {
			pos += result;
		}
		else if (result < 0) {
			if (errno != EWOULDBLOCK) {
				// Common when a client aborts.
				cf_debug(AS_PROTO, "protocol write fail: fd %d sz %zd pos %zd rv %d errno %d", fd_h->fd, msg_sz, pos, rv, errno);
				as_end_of_transaction_force_close(fd_h);
				rv = -1;
				goto Exit;
			}

			usleep(1); // yield
		}
		else {
			cf_info(AS_PROTO, "protocol write fail zero return: fd %d sz %d pos %d ", fd_h->fd, msg_sz, pos);
			as_end_of_transaction_force_close(fd_h);
			rv = -1;
			goto Exit;
		}
	}

	as_end_of_transaction_ok(fd_h);

Exit:
	return rv;
}
Exemplo n.º 4
0
// Security is an enterprise feature. If we receive a security message from a
// client here, quickly return AS_SEC_ERR_NOT_SUPPORTED. The client may choose
// to continue using this (unsecured) socket.
void
as_security_transact(as_transaction* tr)
{
	// We don't need the request, since we're ignoring it.
	cf_free(tr->msgp);
	tr->msgp = NULL;

	// Set up a simple response with a single as_sec_msg that has no fields.
	size_t resp_size = sizeof(as_proto) + sizeof(as_sec_msg);
	uint8_t resp[resp_size];

	// Fill out the as_proto fields.
	as_proto* p_resp_proto = (as_proto*)resp;

	p_resp_proto->version = PROTO_VERSION;
	p_resp_proto->type = PROTO_TYPE_SECURITY;
	p_resp_proto->sz = sizeof(as_sec_msg);

	// Switch to network byte order.
	as_proto_swap(p_resp_proto);

	uint8_t* p_proto_body = resp + sizeof(as_proto);

	memset((void*)p_proto_body, 0, sizeof(as_sec_msg));

	// Fill out the relevant as_sec_msg fields.
	as_sec_msg* p_sec_msg = (as_sec_msg*)p_proto_body;

	p_sec_msg->scheme = AS_SEC_MSG_SCHEME;
	p_sec_msg->result = AS_SEC_ERR_NOT_SUPPORTED;

	// Send the complete response.
	uint8_t* p_write = resp;
	uint8_t* p_end = resp + resp_size;
	int fd = tr->from.proto_fd_h->fd;

	while (p_write < p_end) {
		int rv = send(fd, (void*)p_write, p_end - p_write, MSG_NOSIGNAL);

		if (rv > 0) {
			p_write += rv;
		}
		else if (rv == 0) {
			cf_warning(AS_SECURITY, "fd %d send returned 0", fd);
			as_end_of_transaction_force_close(tr->from.proto_fd_h);
			tr->from.proto_fd_h = NULL;
			return;
		}
		// rv < 0
		else if (errno == EAGAIN || errno == EWOULDBLOCK) {
			usleep(1);
		}
		else {
			cf_warning(AS_SECURITY, "fd %d send failed, errno %d", fd, errno);
			as_end_of_transaction_force_close(tr->from.proto_fd_h);
			tr->from.proto_fd_h = NULL;
			return;
		}
	}

	as_end_of_transaction_ok(tr->from.proto_fd_h);
	tr->from.proto_fd_h = NULL;
}