Exemple #1
0
void EXE_send(thread_db* tdbb, jrd_req* request, USHORT msg, ULONG length, const UCHAR* buffer)
{
/**************************************
 *
 *	E X E _ s e n d
 *
 **************************************
 *
 * Functional description
 *	Send a message from the host program to the engine.
 *	This corresponds to a blr_receive or blr_select statement.
 *
 **************************************/
	SET_TDBB(tdbb);
	DEV_BLKCHK(request, type_req);

	if (--tdbb->tdbb_quantum < 0)
		JRD_reschedule(tdbb, 0, true);

	if (!(request->req_flags & req_active))
		ERR_post(Arg::Gds(isc_req_sync));

	const StmtNode* message = NULL;
	const StmtNode* node;

	if (request->req_operation != jrd_req::req_receive)
		ERR_post(Arg::Gds(isc_req_sync));
	node = request->req_message;

	jrd_tra* transaction = request->req_transaction;
	const JrdStatement* statement = request->getStatement();

	const SelectNode* selectNode;

	if (StmtNode::is<MessageNode>(node))
		message = node;
	else if ((selectNode = StmtNode::as<SelectNode>(node)))
	{
		const NestConst<StmtNode>* ptr = selectNode->statements.begin();

		for (const NestConst<StmtNode>* end = selectNode->statements.end(); ptr != end; ++ptr)
		{
			const ReceiveNode* receiveNode = (*ptr)->as<ReceiveNode>();
			message = receiveNode->message;

			if (message->as<MessageNode>()->messageNumber == msg)
			{
				request->req_next = *ptr;
				break;
			}
		}
	}
	else
		BUGCHECK(167);	// msg 167 invalid SEND request

	const Format* format = StmtNode::as<MessageNode>(message)->format;

	if (msg != StmtNode::as<MessageNode>(message)->messageNumber)
		ERR_post(Arg::Gds(isc_req_sync));

	if (length != format->fmt_length)
		ERR_post(Arg::Gds(isc_port_len) << Arg::Num(length) << Arg::Num(format->fmt_length));

	memcpy(request->getImpure<UCHAR>(message->impureOffset), buffer, length);

	for (USHORT i = 0; i < format->fmt_count; ++i)
	{
		const DSC* desc = &format->fmt_desc[i];

		// ASF: I'll not test for dtype_cstring because usage is only internal
		if (desc->dsc_dtype == dtype_text || desc->dsc_dtype == dtype_varying)
		{
			const UCHAR* p = request->getImpure<UCHAR>(message->impureOffset +
				(ULONG)(IPTR) desc->dsc_address);
			USHORT len;

			switch (desc->dsc_dtype)
			{
				case dtype_text:
					len = desc->dsc_length;
					break;

				case dtype_varying:
					len = reinterpret_cast<const vary*>(p)->vary_length;
					p += sizeof(USHORT);
					break;
			}

			CharSet* charSet = INTL_charset_lookup(tdbb, DSC_GET_CHARSET(desc));

			if (!charSet->wellFormed(len, p))
				ERR_post(Arg::Gds(isc_malformed_string));
		}
		else if (desc->isBlob())
		{
			if (desc->getCharSet() != CS_NONE && desc->getCharSet() != CS_BINARY)
			{
				const Jrd::bid* bid = request->getImpure<Jrd::bid>(
					message->impureOffset + (ULONG)(IPTR) desc->dsc_address);

				if (!bid->isEmpty())
				{
					AutoBlb blob(tdbb, blb::open(tdbb, transaction/*tdbb->getTransaction()*/, bid));
					blob.getBlb()->BLB_check_well_formed(tdbb, desc);
				}
			}
		}
	}

	execute_looper(tdbb, request, transaction, request->req_next, jrd_req::req_proceed);
}
Exemple #2
0
ULONG INTL_convert_bytes(thread_db* tdbb,
						 CHARSET_ID dest_type,
						 BYTE* dest_ptr,
						 const ULONG dest_len,
						 CHARSET_ID src_type,
						 const BYTE* src_ptr,
						 const ULONG src_len,
						 ErrorFunction err)
{
/**************************************
 *
 *      I N T L _ c o n v e r t _ b y t e s
 *
 **************************************
 *
 * Functional description
 *      Given a string of bytes in one character set, convert it to another
 *      character set.
 *
 *      If (dest_ptr) is NULL, return the count of bytes needed to convert
 *      the string.  This does not guarantee the string can be converted,
 *      the purpose of this is to allocate a large enough buffer.
 *
 * RETURNS:
 *      Length of resulting string, in bytes.
 *      calls (err) if conversion error occurs.
 *
 **************************************/
	SET_TDBB(tdbb);

	fb_assert(src_ptr != NULL);
	fb_assert(src_type != dest_type);
	fb_assert(err != NULL);

	dest_type = INTL_charset(tdbb, dest_type);
	src_type = INTL_charset(tdbb, src_type);

	const UCHAR* const start_dest_ptr = dest_ptr;

	if (dest_type == CS_BINARY || dest_type == CS_NONE ||
		src_type == CS_BINARY || src_type == CS_NONE)
	{
		// See if we just need a length estimate
		if (dest_ptr == NULL)
			return (src_len);

		if (dest_type != CS_BINARY && dest_type != CS_NONE)
		{
			CharSet* toCharSet = INTL_charset_lookup(tdbb, dest_type);

			if (!toCharSet->wellFormed(src_len, src_ptr))
				err(Arg::Gds(isc_malformed_string));
		}

		ULONG len = MIN(dest_len, src_len);
		if (len)
		{
			do {
				*dest_ptr++ = *src_ptr++;
			} while (--len);
		}

		// See if only space characters are remaining
		len = src_len - MIN(dest_len, src_len);
		if (len == 0 || allSpaces(INTL_charset_lookup(tdbb, src_type), src_ptr, len, 0))
			return dest_ptr - start_dest_ptr;

		err(Arg::Gds(isc_arith_except) << Arg::Gds(isc_string_truncation) <<
			Arg::Gds(isc_trunc_limits) << Arg::Num(dest_len) << Arg::Num(src_len));
	}
	else if (src_len)
	{
		// character sets are known to be different
		// Do we know an object from cs1 to cs2?

		CsConvert cs_obj = INTL_convert_lookup(tdbb, dest_type, src_type);
		return cs_obj.convert(src_len, src_ptr, dest_len, dest_ptr, NULL, true);
	}

	return 0;
}