8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-27 20:03:03 +01:00
firebird-mirror/src/remote/protocol.cpp

1782 lines
48 KiB
C++
Raw Normal View History

2001-05-23 15:26:42 +02:00
/*
* PROGRAM: JRD Remote Interface/Server
* MODULE: protocol.cpp
2001-05-23 15:26:42 +02:00
* DESCRIPTION: Protocol data structure mapper
*
* The contents of this file are subject to the Interbase Public
* License Version 1.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy
* of the License at http://www.Inprise.com/IPL.html
*
* Software distributed under the License is distributed on an
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
* or implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code was created by Inprise Corporation
* and its predecessors. Portions created by Inprise Corporation are
* Copyright (C) Inprise Corporation.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
2002-02-16 04:27:33 +01:00
*
* 2002.02.15 Sean Leyne - Code Cleanup, removed obsolete "IMP" port
*
* 2002.10.27 Sean Leyne - Code Cleanup, removed obsolete "Ultrix/MIPS" port
* 2002.10.28 Sean Leyne - Code cleanup, removed obsolete "SGI" port
*
2001-05-23 15:26:42 +02:00
*/
#include "firebird.h"
2004-04-29 00:36:29 +02:00
#include <stdio.h>
2001-05-23 15:26:42 +02:00
#include <string.h>
#include "../remote/remote.h"
#include "gen/iberror.h"
2001-05-23 15:26:42 +02:00
#include "../jrd/sdl.h"
#include "../jrd/gdsassert.h"
#include "../remote/parse_proto.h"
#include "../remote/proto_proto.h"
#include "../remote/remot_proto.h"
#include "../jrd/gds_proto.h"
#include "../jrd/sdl_proto.h"
#ifdef DEBUG_XDR_MEMORY
2009-01-14 13:37:23 +01:00
inline bool_t P_TRUE(XDR* xdrs, PACKET* p)
{
2004-05-17 12:22:34 +02:00
return xdr_debug_packet(xdrs, XDR_FREE, p);
}
2009-01-14 13:37:23 +01:00
inline bool_t P_FALSE(XDR* xdrs, PACKET* p)
{
2004-05-17 12:22:34 +02:00
return !xdr_debug_packet(xdrs, XDR_FREE, p);
}
2009-01-14 13:37:23 +01:00
inline void DEBUG_XDR_PACKET(XDR* xdrs, PACKET* p)
{
2004-05-17 12:22:34 +02:00
xdr_debug_packet(xdrs, XDR_DECODE, p);
}
2009-01-14 13:37:23 +01:00
inline void DEBUG_XDR_ALLOC(XDR* xdrs, const void* xdrvar, const void* addr, ULONG len)
{
2004-05-17 12:22:34 +02:00
xdr_debug_memory(xdrs, XDR_DECODE, xdrvar, addr, len);
}
2009-01-14 13:37:23 +01:00
inline void DEBUG_XDR_FREE(XDR* xdrs, const void* xdrvar, const void* addr, ULONG len)
{
2004-05-17 12:22:34 +02:00
xdr_debug_memory(xdrs, XDR_DECODE, xdrvar, addr, len);
}
2001-05-23 15:26:42 +02:00
#else
2009-04-28 15:08:04 +02:00
inline bool_t P_TRUE(XDR*, PACKET*)
2009-01-14 13:37:23 +01:00
{
2004-05-17 12:22:34 +02:00
return TRUE;
}
2009-04-28 15:08:04 +02:00
inline bool_t P_FALSE(XDR*, PACKET*)
2009-01-14 13:37:23 +01:00
{
2004-05-17 12:22:34 +02:00
return FALSE;
}
2009-04-28 15:08:04 +02:00
inline void DEBUG_XDR_PACKET(XDR*, PACKET*)
2009-01-14 13:37:23 +01:00
{
2004-05-17 12:22:34 +02:00
}
2009-04-28 15:08:04 +02:00
inline void DEBUG_XDR_ALLOC(XDR*, const void*, const void*, ULONG)
2009-01-14 13:37:23 +01:00
{
2004-05-17 12:22:34 +02:00
}
2009-04-28 15:08:04 +02:00
inline void DEBUG_XDR_FREE(XDR*, const void*, const void*, ULONG)
2009-01-14 13:37:23 +01:00
{
2004-05-17 12:22:34 +02:00
}
2009-04-16 08:52:08 +02:00
#endif // DEBUG_XDR_MEMORY
2001-05-23 15:26:42 +02:00
2004-05-17 12:22:34 +02:00
#define MAP(routine, ptr) if (!routine (xdrs, &ptr)) return P_FALSE(xdrs, p);
const ULONG MAX_OPAQUE = 32768;
2001-05-23 15:26:42 +02:00
2009-01-14 13:37:23 +01:00
enum SQL_STMT_TYPE
{
2001-05-23 15:26:42 +02:00
TYPE_IMMEDIATE,
TYPE_PREPARED
2009-01-14 13:37:23 +01:00
};
2001-05-23 15:26:42 +02:00
2009-04-16 08:52:08 +02:00
static bool alloc_cstring(XDR*, CSTRING*);
static void free_cstring(XDR*, CSTRING*);
static Rsr* get_statement(XDR*, SSHORT);
static bool_t xdr_cstring(XDR*, CSTRING*);
static inline bool_t xdr_cstring_const(XDR*, CSTRING_CONST*);
2009-04-16 08:52:08 +02:00
static bool_t xdr_datum(XDR*, const DSC*, BLOB_PTR*);
#ifdef DEBUG_XDR_MEMORY
2009-04-16 08:52:08 +02:00
static bool_t xdr_debug_packet(XDR*, enum xdr_op, PACKET*);
#endif
2009-04-16 08:52:08 +02:00
static bool_t xdr_longs(XDR*, CSTRING*);
static bool_t xdr_message(XDR*, RMessage*, const rem_fmt*);
static bool_t xdr_quad(XDR*, struct bid*);
static bool_t xdr_request(XDR*, USHORT, USHORT, USHORT);
2009-04-28 15:08:04 +02:00
static bool_t xdr_slice(XDR*, lstring*, /*USHORT,*/ const UCHAR*);
2009-04-16 08:52:08 +02:00
static bool_t xdr_status_vector(XDR*, ISC_STATUS*, TEXT * strings[]);
static bool_t xdr_sql_blr(XDR*, SLONG, CSTRING*, bool, SQL_STMT_TYPE);
2009-04-16 08:52:08 +02:00
static bool_t xdr_sql_message(XDR*, SLONG);
static bool_t xdr_trrq_blr(XDR*, CSTRING*);
2009-04-16 08:52:08 +02:00
static bool_t xdr_trrq_message(XDR*, USHORT);
2001-05-23 15:26:42 +02:00
2009-06-27 10:28:07 +02:00
#include "../remote/xdr_proto.h"
2001-05-23 15:26:42 +02:00
#ifdef DEBUG
static ULONG xdr_save_size = 0;
2009-01-16 10:55:38 +01:00
inline void DEBUG_PRINTSIZE(XDR* xdrs, P_OP p)
{
2004-05-17 12:22:34 +02:00
fprintf (stderr, "xdr_protocol: %s op %d size %lu\n",
((xdrs->x_op == XDR_FREE) ? "free" :
2009-01-16 10:55:38 +01:00
(xdrs->x_op == XDR_ENCODE) ? "enc " : (xdrs->x_op == XDR_DECODE) ? "dec " : "othr"),
2004-12-16 04:03:13 +01:00
p,
((xdrs->x_op == XDR_ENCODE) ?
(xdrs->x_handy - xdr_save_size) : (xdr_save_size - xdrs->x_handy)));
2004-05-17 12:22:34 +02:00
}
#else
2009-04-28 15:08:04 +02:00
inline void DEBUG_PRINTSIZE(XDR*, P_OP)
2009-01-16 10:55:38 +01:00
{
2004-05-17 12:22:34 +02:00
}
2001-05-23 15:26:42 +02:00
#endif
#ifdef DEBUG_XDR_MEMORY
2009-01-16 10:55:38 +01:00
void xdr_debug_memory(XDR* xdrs,
2001-05-23 15:26:42 +02:00
enum xdr_op xop,
const void* xdrvar, const void* address, ULONG length)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* x d r _ d e b u g _ m e m o r y
*
**************************************
*
* Functional description
* Track memory allocation patterns of XDR aggregate
* types (i.e. xdr_cstring, xdr_string, etc.) to
* validate that memory is not leaked by overwriting
* XDR aggregate pointers and that freeing a packet
* with REMOTE_free_packet() does not miss anything.
*
* All memory allocations due to marshalling XDR
* variables are recorded in a debug memory alloca-
* tion table stored at the front of a packet.
*
* Once a packet is being tracked it is an assertion
* error if a memory allocation can not be recorded
* due to space limitations or if a previous memory
* allocation being freed cannot be found. At most
* P_MALLOC_SIZE entries can be stored in the memory
* allocation table. A rough estimate of the number
* of XDR aggregates that can hang off a packet can
* be obtained by examining the subpackets defined
* in <remote/protocol.h>: A guestimate of 36 at this
* time includes 10 strings used to decode an xdr
* status vector.
*
**************************************/
rem_port* port = (rem_port*) xdrs->x_public;
2003-11-04 00:59:24 +01:00
fb_assert(port != 0);
fb_assert(port->port_header.blk_type == type_port);
2001-05-23 15:26:42 +02:00
2009-04-16 08:52:08 +02:00
// Compare the XDR variable address with the lower and upper bounds
// of each packet to determine which packet contains it. Record or
// delete an entry in that packet's memory allocation table.
2001-05-23 15:26:42 +02:00
rem_vec* vector = port->port_packet_vector;
2009-04-16 08:52:08 +02:00
if (!vector) // Not tracking port's protocol
2001-05-23 15:26:42 +02:00
return;
ULONG i;
2009-01-16 10:55:38 +01:00
for (i = 0; i < vector->vec_count; i++)
{
PACKET* packet = (PACKET*) vector->vec_object[i];
2009-01-16 10:55:38 +01:00
if (packet)
{
2008-12-31 06:06:08 +01:00
fb_assert(packet->p_operation > op_void && packet->p_operation < op_max);
2001-05-23 15:26:42 +02:00
2009-04-16 08:52:08 +02:00
if ((SCHAR*) xdrvar >= (SCHAR*) packet &&
(SCHAR*) xdrvar < (SCHAR*) packet + sizeof(PACKET))
2004-09-22 10:49:50 +02:00
{
ULONG j;
2009-01-16 10:55:38 +01:00
for (j = 0; j < P_MALLOC_SIZE; j++)
{
if (xop == XDR_FREE)
{
2009-04-16 08:52:08 +02:00
if ((SCHAR*) packet->p_malloc[j].p_address == (SCHAR*) address)
2004-09-22 10:49:50 +02:00
{
2001-05-23 15:26:42 +02:00
packet->p_malloc[j].p_operation = op_void;
packet->p_malloc[j].p_allocated = NULL;
packet->p_malloc[j].p_address = 0;
2009-04-16 08:52:08 +02:00
// packet->p_malloc [j].p_xdrvar = 0;
2001-05-23 15:26:42 +02:00
return;
}
}
2009-06-28 12:26:25 +02:00
else
{ // XDR_ENCODE or XDR_DECODE
2001-05-23 15:26:42 +02:00
2003-11-04 00:59:24 +01:00
fb_assert(xop == XDR_ENCODE || xop == XDR_DECODE);
2001-05-23 15:26:42 +02:00
if (packet->p_malloc[j].p_operation == op_void) {
2009-01-16 10:55:38 +01:00
packet->p_malloc[j].p_operation = packet->p_operation;
2001-05-23 15:26:42 +02:00
packet->p_malloc[j].p_allocated = length;
packet->p_malloc[j].p_address = address;
2009-04-16 08:52:08 +02:00
// packet->p_malloc [j].p_xdrvar = xdrvar;
2001-05-23 15:26:42 +02:00
return;
}
}
}
2009-04-16 08:52:08 +02:00
// Assertion failure if not enough entries to record every xdr
// memory allocation or an entry to be freed can't be found.
2001-05-23 15:26:42 +02:00
2009-04-16 08:52:08 +02:00
fb_assert(j < P_MALLOC_SIZE); // Increase P_MALLOC_SIZE if necessary
2001-05-23 15:26:42 +02:00
}
}
}
2009-04-16 08:52:08 +02:00
fb_assert(i < vector->vec_count); // Couldn't find packet for this xdr arg
2001-05-23 15:26:42 +02:00
}
#endif
bool_t xdr_protocol(XDR* xdrs, PACKET* p)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* x d r _ p r o t o c o l
*
**************************************
*
* Functional description
* Encode, decode, or free a protocol packet.
*
**************************************/
2009-06-27 08:23:36 +02:00
p_cnct::p_cnct_repeat* tail;
2008-01-16 08:55:28 +01:00
const rem_port* port;
2001-05-23 15:26:42 +02:00
P_ACPT *accept;
P_ATCH *attach;
P_RESP *response;
P_CMPL *compile;
P_STTR *transaction;
P_DATA *data;
P_RLSE *release;
P_BLOB *blob;
P_SGMT *segment;
P_INFO *info;
P_PREP *prepare;
P_REQ *request;
P_DDL *ddl;
P_SLC *slice;
P_SLR *slice_response;
P_SEEK *seek;
P_SQLFREE *free_stmt;
P_SQLCUR *sqlcur;
P_SQLST *prep_stmt;
P_SQLDATA *sqldata;
P_TRRQ *trrq;
2006-12-08 19:38:15 +01:00
P_TRAU *trau;
P_CANCEL_OP *cancel_op;
2001-05-23 15:26:42 +02:00
#ifdef DEBUG
xdr_save_size = xdrs->x_handy;
#endif
2004-05-17 12:22:34 +02:00
DEBUG_XDR_PACKET(xdrs, p);
2001-05-23 15:26:42 +02:00
2004-10-08 10:13:22 +02:00
if (!xdr_enum(xdrs, reinterpret_cast<xdr_op*>(&p->p_operation)))
2004-05-17 12:22:34 +02:00
return P_FALSE(xdrs, p);
2001-05-23 15:26:42 +02:00
switch (p->p_operation)
{
2001-05-23 15:26:42 +02:00
case op_reject:
case op_disconnect:
case op_dummy:
2004-05-17 12:22:34 +02:00
return P_TRUE(xdrs, p);
2001-05-23 15:26:42 +02:00
case op_connect:
{
2008-01-16 08:55:28 +01:00
P_CNCT* connect = &p->p_cnct;
2009-01-16 10:55:38 +01:00
MAP(xdr_enum, reinterpret_cast<xdr_op&>(connect->p_cnct_operation));
MAP(xdr_short, reinterpret_cast<SSHORT&>(connect->p_cnct_cversion));
MAP(xdr_enum, reinterpret_cast<xdr_op&>(connect->p_cnct_client));
MAP(xdr_cstring_const, connect->p_cnct_file);
MAP(xdr_short, reinterpret_cast<SSHORT&>(connect->p_cnct_count));
MAP(xdr_cstring_const, connect->p_cnct_user_id);
2009-06-27 08:23:36 +02:00
USHORT i;
const size_t CNCT_VERSIONS = FB_NELEM(connect->p_cnct_versions);
2009-01-16 10:55:38 +01:00
for (i = 0, tail = connect->p_cnct_versions; i < connect->p_cnct_count; i++, tail++)
{
// ignore the rest of protocols in case of too many suggested versions
p_cnct::p_cnct_repeat dummy;
if (i >= CNCT_VERSIONS)
{
tail = &dummy;
}
2008-12-05 02:20:14 +01:00
2009-01-16 10:55:38 +01:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(tail->p_cnct_version));
MAP(xdr_enum, reinterpret_cast<xdr_op&>(tail->p_cnct_architecture));
MAP(xdr_u_short, tail->p_cnct_min_type);
MAP(xdr_u_short, tail->p_cnct_max_type);
2009-01-16 10:55:38 +01:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(tail->p_cnct_weight));
}
// ignore the rest of protocols in case of too many suggested versions
if (connect->p_cnct_count > CNCT_VERSIONS)
{
connect->p_cnct_count = CNCT_VERSIONS;
}
2008-12-05 02:20:14 +01:00
DEBUG_PRINTSIZE(xdrs, p->p_operation);
return P_TRUE(xdrs, p);
2001-05-23 15:26:42 +02:00
}
case op_accept:
accept = &p->p_acpt;
2004-10-08 10:13:22 +02:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(accept->p_acpt_version));
2009-01-16 10:55:38 +01:00
MAP(xdr_enum, reinterpret_cast<xdr_op&>(accept->p_acpt_architecture));
2001-05-23 15:26:42 +02:00
MAP(xdr_u_short, accept->p_acpt_type);
2004-05-17 12:22:34 +02:00
DEBUG_PRINTSIZE(xdrs, p->p_operation);
return P_TRUE(xdrs, p);
2001-05-23 15:26:42 +02:00
case op_connect_request:
case op_aux_connect:
request = &p->p_req;
2004-10-08 10:13:22 +02:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(request->p_req_type));
MAP(xdr_short, reinterpret_cast<SSHORT&>(request->p_req_object));
MAP(xdr_long, reinterpret_cast<SLONG&>(request->p_req_partner));
2004-05-17 12:22:34 +02:00
DEBUG_PRINTSIZE(xdrs, p->p_operation);
return P_TRUE(xdrs, p);
2001-05-23 15:26:42 +02:00
case op_attach:
case op_create:
case op_service_attach:
attach = &p->p_atch;
2009-01-16 10:55:38 +01:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(attach->p_atch_database));
MAP(xdr_cstring_const, attach->p_atch_file);
MAP(xdr_cstring_const, attach->p_atch_dpb);
2004-05-17 12:22:34 +02:00
DEBUG_PRINTSIZE(xdrs, p->p_operation);
return P_TRUE(xdrs, p);
2001-05-23 15:26:42 +02:00
case op_compile:
compile = &p->p_cmpl;
2009-01-16 10:55:38 +01:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(compile->p_cmpl_database));
MAP(xdr_cstring_const, compile->p_cmpl_blr);
2004-05-17 12:22:34 +02:00
DEBUG_PRINTSIZE(xdrs, p->p_operation);
return P_TRUE(xdrs, p);
2001-05-23 15:26:42 +02:00
case op_receive:
case op_start:
case op_start_and_receive:
data = &p->p_data;
2004-10-08 10:13:22 +02:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(data->p_data_request));
2009-01-16 10:55:38 +01:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(data->p_data_incarnation));
MAP(xdr_short, reinterpret_cast<SSHORT&>(data->p_data_transaction));
MAP(xdr_short, reinterpret_cast<SSHORT&>(data->p_data_message_number));
2004-10-08 10:13:22 +02:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(data->p_data_messages));
2001-05-23 15:26:42 +02:00
#ifdef SCROLLABLE_CURSORS
port = (rem_port*) xdrs->x_public;
2009-01-16 10:55:38 +01:00
if ((p->p_operation == op_receive) && (port->port_protocol > PROTOCOL_VERSION8))
2004-09-22 10:49:50 +02:00
{
2009-01-16 10:55:38 +01:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(data->p_data_direction));
2008-01-16 08:55:28 +01:00
MAP(xdr_long, reinterpret_cast<SLONG&>(data->p_data_offset));
2001-05-23 15:26:42 +02:00
}
#endif
2004-05-17 12:22:34 +02:00
DEBUG_PRINTSIZE(xdrs, p->p_operation);
return P_TRUE(xdrs, p);
2001-05-23 15:26:42 +02:00
case op_send:
case op_start_and_send:
case op_start_send_and_receive:
data = &p->p_data;
2004-10-08 10:13:22 +02:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(data->p_data_request));
2009-01-16 10:55:38 +01:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(data->p_data_incarnation));
MAP(xdr_short, reinterpret_cast<SSHORT&>(data->p_data_transaction));
MAP(xdr_short, reinterpret_cast<SSHORT&>(data->p_data_message_number));
2004-10-08 10:13:22 +02:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(data->p_data_messages));
2001-05-23 15:26:42 +02:00
2009-04-16 08:52:08 +02:00
// Changes to this op's protocol must mirror in xdr_protocol_overhead
2001-05-23 15:26:42 +02:00
return xdr_request(xdrs, data->p_data_request,
data->p_data_message_number,
2004-05-17 12:22:34 +02:00
data->p_data_incarnation) ? P_TRUE(xdrs, p) : P_FALSE(xdrs, p);
2001-05-23 15:26:42 +02:00
case op_response:
case op_response_piggyback:
2009-04-16 08:52:08 +02:00
// Changes to this op's protocol must be mirrored
// in xdr_protocol_overhead
2001-05-23 15:26:42 +02:00
response = &p->p_resp;
2009-01-16 10:55:38 +01:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(response->p_resp_object));
2001-05-23 15:26:42 +02:00
MAP(xdr_quad, response->p_resp_blob_id);
MAP(xdr_cstring, response->p_resp_data);
return xdr_status_vector(xdrs, response->p_resp_status_vector,
2009-01-03 10:14:29 +01:00
reinterpret_cast<char**>(response->p_resp_strings)) ?
P_TRUE(xdrs, p) : P_FALSE(xdrs, p);
2001-05-23 15:26:42 +02:00
case op_transact:
trrq = &p->p_trrq;
2004-10-08 10:13:22 +02:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(trrq->p_trrq_database));
2009-01-16 10:55:38 +01:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(trrq->p_trrq_transaction));
2001-05-23 15:26:42 +02:00
xdr_trrq_blr(xdrs, &trrq->p_trrq_blr);
MAP(xdr_cstring, trrq->p_trrq_blr);
2004-10-08 10:13:22 +02:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(trrq->p_trrq_messages));
2001-05-23 15:26:42 +02:00
if (trrq->p_trrq_messages)
2004-05-17 12:22:34 +02:00
return xdr_trrq_message(xdrs, 0) ? P_TRUE(xdrs, p) : P_FALSE(xdrs, p);
DEBUG_PRINTSIZE(xdrs, p->p_operation);
return P_TRUE(xdrs, p);
2001-05-23 15:26:42 +02:00
case op_transact_response:
data = &p->p_data;
2004-10-08 10:13:22 +02:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(data->p_data_messages));
2001-05-23 15:26:42 +02:00
if (data->p_data_messages)
2004-05-17 12:22:34 +02:00
return xdr_trrq_message(xdrs, 1) ? P_TRUE(xdrs, p) : P_FALSE(xdrs, p);
DEBUG_PRINTSIZE(xdrs, p->p_operation);
return P_TRUE(xdrs, p);
2001-05-23 15:26:42 +02:00
case op_open_blob2:
case op_create_blob2:
blob = &p->p_blob;
MAP(xdr_cstring_const, blob->p_blob_bpb);
// fall into:
2001-05-23 15:26:42 +02:00
case op_open_blob:
case op_create_blob:
blob = &p->p_blob;
2009-01-16 10:55:38 +01:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(blob->p_blob_transaction));
2001-05-23 15:26:42 +02:00
MAP(xdr_quad, blob->p_blob_id);
2004-05-17 12:22:34 +02:00
DEBUG_PRINTSIZE(xdrs, p->p_operation);
return P_TRUE(xdrs, p);
2001-05-23 15:26:42 +02:00
case op_get_segment:
case op_put_segment:
case op_batch_segments:
segment = &p->p_sgmt;
2004-10-08 10:13:22 +02:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(segment->p_sgmt_blob));
MAP(xdr_short, reinterpret_cast<SSHORT&>(segment->p_sgmt_length));
MAP(xdr_cstring_const, segment->p_sgmt_segment);
2004-05-17 12:22:34 +02:00
DEBUG_PRINTSIZE(xdrs, p->p_operation);
return P_TRUE(xdrs, p);
2001-05-23 15:26:42 +02:00
case op_seek_blob:
seek = &p->p_seek;
2004-10-08 10:13:22 +02:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(seek->p_seek_blob));
MAP(xdr_short, reinterpret_cast<SSHORT&>(seek->p_seek_mode));
2001-05-23 15:26:42 +02:00
MAP(xdr_long, seek->p_seek_offset);
2004-05-17 12:22:34 +02:00
DEBUG_PRINTSIZE(xdrs, p->p_operation);
return P_TRUE(xdrs, p);
2001-05-23 15:26:42 +02:00
case op_reconnect:
case op_transaction:
transaction = &p->p_sttr;
2009-01-16 10:55:38 +01:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(transaction->p_sttr_database));
MAP(xdr_cstring_const, transaction->p_sttr_tpb);
2004-05-17 12:22:34 +02:00
DEBUG_PRINTSIZE(xdrs, p->p_operation);
return P_TRUE(xdrs, p);
2001-05-23 15:26:42 +02:00
case op_info_blob:
case op_info_database:
case op_info_request:
case op_info_transaction:
case op_service_info:
case op_info_sql:
info = &p->p_info;
2004-10-08 10:13:22 +02:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(info->p_info_object));
2009-01-16 10:55:38 +01:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(info->p_info_incarnation));
MAP(xdr_cstring_const, info->p_info_items);
2001-05-23 15:26:42 +02:00
if (p->p_operation == op_service_info)
MAP(xdr_cstring_const, info->p_info_recv_items);
MAP(xdr_short, reinterpret_cast<SSHORT&>(info->p_info_buffer_length));
2004-05-17 12:22:34 +02:00
DEBUG_PRINTSIZE(xdrs, p->p_operation);
return P_TRUE(xdrs, p);
2001-05-23 15:26:42 +02:00
case op_service_start:
info = &p->p_info;
2004-10-08 10:13:22 +02:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(info->p_info_object));
2009-01-16 10:55:38 +01:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(info->p_info_incarnation));
MAP(xdr_cstring_const, info->p_info_items);
2004-05-17 12:22:34 +02:00
DEBUG_PRINTSIZE(xdrs, p->p_operation);
return P_TRUE(xdrs, p);
2001-05-23 15:26:42 +02:00
case op_commit:
case op_prepare:
case op_rollback:
case op_unwind:
case op_release:
case op_close_blob:
case op_cancel_blob:
case op_detach:
case op_drop_database:
case op_service_detach:
case op_commit_retaining:
case op_rollback_retaining:
case op_allocate_statement:
release = &p->p_rlse;
2004-10-08 10:13:22 +02:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(release->p_rlse_object));
2004-05-17 12:22:34 +02:00
DEBUG_PRINTSIZE(xdrs, p->p_operation);
return P_TRUE(xdrs, p);
2001-05-23 15:26:42 +02:00
case op_prepare2:
prepare = &p->p_prep;
2009-01-16 10:55:38 +01:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(prepare->p_prep_transaction));
MAP(xdr_cstring_const, prepare->p_prep_data);
2004-05-17 12:22:34 +02:00
DEBUG_PRINTSIZE(xdrs, p->p_operation);
return P_TRUE(xdrs, p);
2001-05-23 15:26:42 +02:00
case op_que_events:
case op_event:
2003-12-22 11:00:59 +01:00
{
2008-01-16 08:55:28 +01:00
P_EVENT* event = &p->p_event;
2009-01-16 10:55:38 +01:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(event->p_event_database));
MAP(xdr_cstring_const, event->p_event_items);
2008-12-05 02:20:14 +01:00
// Nickolay Samofatov: these values are parsed, but are ignored by the client.
// Values are useful only for debugging, anyway since upper words of pointers
// are trimmed for 64-bit clients
2003-12-22 11:00:59 +01:00
MAP(xdr_long, reinterpret_cast<SLONG&>(event->p_event_ast));
MAP(xdr_long, event->p_event_arg);
2008-12-05 02:20:14 +01:00
2003-12-22 11:00:59 +01:00
MAP(xdr_long, event->p_event_rid);
2004-05-17 12:22:34 +02:00
DEBUG_PRINTSIZE(xdrs, p->p_operation);
return P_TRUE(xdrs, p);
2003-12-22 11:00:59 +01:00
}
2001-05-23 15:26:42 +02:00
case op_cancel_events:
2008-01-16 08:55:28 +01:00
{
P_EVENT* event = &p->p_event;
2009-01-16 10:55:38 +01:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(event->p_event_database));
2008-01-16 08:55:28 +01:00
MAP(xdr_long, event->p_event_rid);
DEBUG_PRINTSIZE(xdrs, p->p_operation);
return P_TRUE(xdrs, p);
}
2001-05-23 15:26:42 +02:00
case op_ddl:
ddl = &p->p_ddl;
2004-10-08 10:13:22 +02:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(ddl->p_ddl_database));
MAP(xdr_short, reinterpret_cast<SSHORT&>(ddl->p_ddl_transaction));
MAP(xdr_cstring_const, ddl->p_ddl_blr);
2004-05-17 12:22:34 +02:00
DEBUG_PRINTSIZE(xdrs, p->p_operation);
return P_TRUE(xdrs, p);
2001-05-23 15:26:42 +02:00
case op_get_slice:
case op_put_slice:
slice = &p->p_slc;
2009-01-16 10:55:38 +01:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(slice->p_slc_transaction));
2001-05-23 15:26:42 +02:00
MAP(xdr_quad, slice->p_slc_id);
2004-10-08 10:13:22 +02:00
MAP(xdr_long, reinterpret_cast<SLONG&>(slice->p_slc_length));
2001-05-23 15:26:42 +02:00
MAP(xdr_cstring, slice->p_slc_sdl);
MAP(xdr_longs, slice->p_slc_parameters);
slice_response = &p->p_slr;
2009-06-28 12:26:25 +02:00
if (slice_response->p_slr_sdl)
{
2009-04-28 15:08:04 +02:00
if (!xdr_slice(xdrs, &slice->p_slc_slice, //slice_response->p_slr_sdl_length,
2008-12-05 02:20:14 +01:00
slice_response->p_slr_sdl))
{
2004-05-17 12:22:34 +02:00
return P_FALSE(xdrs, p);
}
2001-05-23 15:26:42 +02:00
}
else
2009-04-28 15:08:04 +02:00
if (!xdr_slice(xdrs, &slice->p_slc_slice, //slice->p_slc_sdl.cstr_length,
2008-12-05 02:20:14 +01:00
slice->p_slc_sdl.cstr_address))
{
2004-05-17 12:22:34 +02:00
return P_FALSE(xdrs, p);
}
2004-05-17 12:22:34 +02:00
DEBUG_PRINTSIZE(xdrs, p->p_operation);
return P_TRUE(xdrs, p);
2001-05-23 15:26:42 +02:00
case op_slice:
slice_response = &p->p_slr;
2009-01-16 10:55:38 +01:00
MAP(xdr_long, reinterpret_cast<SLONG&>(slice_response->p_slr_length));
2009-04-28 15:08:04 +02:00
if (!xdr_slice (xdrs, &slice_response->p_slr_slice, //slice_response->p_slr_sdl_length,
2008-12-05 02:20:14 +01:00
slice_response->p_slr_sdl))
{
2004-05-17 12:22:34 +02:00
return P_FALSE(xdrs, p);
}
2004-05-17 12:22:34 +02:00
DEBUG_PRINTSIZE(xdrs, p->p_operation);
return P_TRUE(xdrs, p);
2001-05-23 15:26:42 +02:00
case op_execute:
case op_execute2:
sqldata = &p->p_sqldata;
2009-01-16 10:55:38 +01:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(sqldata->p_sqldata_statement));
MAP(xdr_short, reinterpret_cast<SSHORT&>(sqldata->p_sqldata_transaction));
if (xdrs->x_op == XDR_DECODE)
{
2009-04-16 08:52:08 +02:00
// the statement should be reset for each execution so that
// all prefetched information from a prior execute is properly
// cleared out. This should be done before fetching any message
// information (for example: blr info)
2001-05-23 15:26:42 +02:00
2008-03-30 11:38:24 +02:00
Rsr* statement = NULL;
2001-05-23 15:26:42 +02:00
statement = get_statement(xdrs, sqldata->p_sqldata_statement);
if (statement)
REMOTE_reset_statement(statement);
}
xdr_sql_blr(xdrs, (SLONG) sqldata->p_sqldata_statement,
&sqldata->p_sqldata_blr, false, TYPE_PREPARED);
2009-01-16 10:55:38 +01:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(sqldata->p_sqldata_message_number));
MAP(xdr_short, reinterpret_cast<SSHORT&>(sqldata->p_sqldata_messages));
2009-06-28 12:26:25 +02:00
if (sqldata->p_sqldata_messages)
{
2001-05-23 15:26:42 +02:00
if (!xdr_sql_message(xdrs, (SLONG) sqldata->p_sqldata_statement))
2004-05-17 12:22:34 +02:00
return P_FALSE(xdrs, p);
2001-05-23 15:26:42 +02:00
}
2009-06-28 12:26:25 +02:00
if (p->p_operation == op_execute2)
{
2009-01-16 10:55:38 +01:00
xdr_sql_blr(xdrs, (SLONG) - 1, &sqldata->p_sqldata_out_blr, true, TYPE_PREPARED);
MAP(xdr_short, reinterpret_cast<SSHORT&>(sqldata->p_sqldata_out_message_number));
2001-05-23 15:26:42 +02:00
}
2004-05-17 12:22:34 +02:00
DEBUG_PRINTSIZE(xdrs, p->p_operation);
return P_TRUE(xdrs, p);
2001-05-23 15:26:42 +02:00
case op_exec_immediate2:
prep_stmt = &p->p_sqlst;
2009-01-16 10:55:38 +01:00
xdr_sql_blr(xdrs, (SLONG) - 1, &prep_stmt->p_sqlst_blr, false, TYPE_IMMEDIATE);
MAP(xdr_short, reinterpret_cast<SSHORT&>(prep_stmt->p_sqlst_message_number));
MAP(xdr_short, reinterpret_cast<SSHORT&>(prep_stmt->p_sqlst_messages));
2009-06-28 12:26:25 +02:00
if (prep_stmt->p_sqlst_messages)
{
2001-05-23 15:26:42 +02:00
if (!xdr_sql_message(xdrs, (SLONG) - 1))
2004-05-17 12:22:34 +02:00
return P_FALSE(xdrs, p);
2001-05-23 15:26:42 +02:00
}
2009-01-16 10:55:38 +01:00
xdr_sql_blr(xdrs, (SLONG) - 1, &prep_stmt->p_sqlst_out_blr, true, TYPE_IMMEDIATE);
MAP(xdr_short, reinterpret_cast<SSHORT&>(prep_stmt->p_sqlst_out_message_number));
2009-04-16 08:52:08 +02:00
// Fall into ...
2001-05-23 15:26:42 +02:00
case op_exec_immediate:
case op_prepare_statement:
prep_stmt = &p->p_sqlst;
2009-01-16 10:55:38 +01:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(prep_stmt->p_sqlst_transaction));
MAP(xdr_short, reinterpret_cast<SSHORT&>(prep_stmt->p_sqlst_statement));
MAP(xdr_short, reinterpret_cast<SSHORT&>(prep_stmt->p_sqlst_SQL_dialect));
MAP(xdr_cstring_const, prep_stmt->p_sqlst_SQL_str);
MAP(xdr_cstring_const, prep_stmt->p_sqlst_items);
2009-01-16 10:55:38 +01:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(prep_stmt->p_sqlst_buffer_length));
2004-05-17 12:22:34 +02:00
DEBUG_PRINTSIZE(xdrs, p->p_operation);
return P_TRUE(xdrs, p);
2001-05-23 15:26:42 +02:00
case op_fetch:
sqldata = &p->p_sqldata;
2009-05-02 15:00:09 +02:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(sqldata->p_sqldata_statement));
2001-05-23 15:26:42 +02:00
xdr_sql_blr(xdrs, (SLONG) sqldata->p_sqldata_statement,
&sqldata->p_sqldata_blr, true, TYPE_PREPARED);
2009-01-16 10:55:38 +01:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(sqldata->p_sqldata_message_number));
MAP(xdr_short, reinterpret_cast<SSHORT&>(sqldata->p_sqldata_messages));
2004-05-17 12:22:34 +02:00
DEBUG_PRINTSIZE(xdrs, p->p_operation);
return P_TRUE(xdrs, p);
2001-05-23 15:26:42 +02:00
case op_fetch_response:
sqldata = &p->p_sqldata;
2009-01-16 10:55:38 +01:00
MAP(xdr_long, reinterpret_cast<SLONG&>(sqldata->p_sqldata_status));
MAP(xdr_short, reinterpret_cast<SSHORT&>(sqldata->p_sqldata_messages));
2001-05-23 15:26:42 +02:00
2009-04-16 08:52:08 +02:00
// Changes to this op's protocol must mirror in xdr_protocol_overhead
2001-05-23 15:26:42 +02:00
port = (rem_port*) xdrs->x_public;
2008-12-31 06:06:08 +01:00
if ((port->port_protocol > PROTOCOL_VERSION7 && sqldata->p_sqldata_messages) ||
(port->port_protocol <= PROTOCOL_VERSION7 && !sqldata->p_sqldata_status))
2004-09-22 10:49:50 +02:00
{
return xdr_sql_message(xdrs, (SLONG)sqldata->p_sqldata_statement) ?
P_TRUE(xdrs, p) : P_FALSE(xdrs, p);
}
2004-05-17 12:22:34 +02:00
DEBUG_PRINTSIZE(xdrs, p->p_operation);
return P_TRUE(xdrs, p);
2001-05-23 15:26:42 +02:00
case op_free_statement:
free_stmt = &p->p_sqlfree;
2008-12-31 06:06:08 +01:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(free_stmt->p_sqlfree_statement));
MAP(xdr_short, reinterpret_cast<SSHORT&>(free_stmt->p_sqlfree_option));
2004-05-17 12:22:34 +02:00
DEBUG_PRINTSIZE(xdrs, p->p_operation);
return P_TRUE(xdrs, p);
2001-05-23 15:26:42 +02:00
case op_insert:
sqldata = &p->p_sqldata;
2008-12-31 06:06:08 +01:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(sqldata->p_sqldata_statement));
2001-05-23 15:26:42 +02:00
xdr_sql_blr(xdrs, (SLONG) sqldata->p_sqldata_statement,
&sqldata->p_sqldata_blr, false, TYPE_PREPARED);
2008-12-31 06:06:08 +01:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(sqldata->p_sqldata_message_number));
2009-01-16 10:55:38 +01:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(sqldata->p_sqldata_messages));
2001-05-23 15:26:42 +02:00
if (sqldata->p_sqldata_messages)
2009-01-16 10:55:38 +01:00
return xdr_sql_message(xdrs, (SLONG) sqldata->p_sqldata_statement) ?
P_TRUE(xdrs, p) : P_FALSE(xdrs, p);
2004-05-17 12:22:34 +02:00
DEBUG_PRINTSIZE(xdrs, p->p_operation);
return P_TRUE(xdrs, p);
2001-05-23 15:26:42 +02:00
case op_set_cursor:
sqlcur = &p->p_sqlcur;
2009-01-16 10:55:38 +01:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(sqlcur->p_sqlcur_statement));
MAP(xdr_cstring_const, sqlcur->p_sqlcur_cursor_name);
2004-10-08 10:13:22 +02:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(sqlcur->p_sqlcur_type));
2004-05-17 12:22:34 +02:00
DEBUG_PRINTSIZE(xdrs, p->p_operation);
return P_TRUE(xdrs, p);
2001-05-23 15:26:42 +02:00
case op_sql_response:
sqldata = &p->p_sqldata;
2009-01-16 10:55:38 +01:00
MAP(xdr_short, reinterpret_cast<SSHORT&>(sqldata->p_sqldata_messages));
2001-05-23 15:26:42 +02:00
if (sqldata->p_sqldata_messages)
2004-05-17 12:22:34 +02:00
return xdr_sql_message(xdrs, (SLONG) - 1) ? P_TRUE(xdrs, p) : P_FALSE(xdrs, p);
DEBUG_PRINTSIZE(xdrs, p->p_operation);
return P_TRUE(xdrs, p);
2001-05-23 15:26:42 +02:00
2006-12-08 19:38:15 +01:00
// the following added to have formal vulcan compatibility
case op_update_account_info:
{
2008-01-16 08:55:28 +01:00
p_update_account *stuff = &p->p_account_update;
MAP(xdr_short, reinterpret_cast<SSHORT&>(stuff->p_account_database));
2008-01-16 08:55:28 +01:00
MAP(xdr_cstring_const, stuff->p_account_apb);
DEBUG_PRINTSIZE(xdrs, p->p_operation);
2006-12-08 19:38:15 +01:00
2008-01-16 08:55:28 +01:00
return P_TRUE(xdrs, p);
2006-12-08 19:38:15 +01:00
}
2008-12-05 02:20:14 +01:00
2006-12-08 19:38:15 +01:00
case op_authenticate_user:
{
2008-01-16 08:55:28 +01:00
p_authenticate *stuff = &p->p_authenticate_user;
MAP(xdr_short, reinterpret_cast<SSHORT&>(stuff->p_auth_database));
2008-01-16 08:55:28 +01:00
MAP(xdr_cstring_const, stuff->p_auth_dpb);
MAP(xdr_cstring, stuff->p_auth_items);
MAP(xdr_short, reinterpret_cast<SSHORT&>(stuff->p_auth_buffer_length));
2008-01-16 08:55:28 +01:00
DEBUG_PRINTSIZE(xdrs, p->p_operation);
2006-12-08 19:38:15 +01:00
2008-01-16 08:55:28 +01:00
return P_TRUE(xdrs, p);
2006-12-08 19:38:15 +01:00
}
case op_trusted_auth:
trau = &p->p_trau;
MAP(xdr_cstring, trau->p_trau_data);
DEBUG_PRINTSIZE(xdrs, p->p_operation);
return P_TRUE(xdrs, p);
case op_cancel:
cancel_op = &p->p_cancel_op;
MAP(xdr_short, reinterpret_cast<SSHORT&>(cancel_op->p_co_kind));
DEBUG_PRINTSIZE(xdrs, p->p_operation);
return P_TRUE(xdrs, p);
2001-05-23 15:26:42 +02:00
default:
#ifdef DEV_BUILD
2001-05-23 15:26:42 +02:00
if (xdrs->x_op != XDR_FREE)
{
gds__log("xdr_packet: operation %d not recognized\n", p->p_operation);
}
#endif
2004-05-17 12:22:34 +02:00
return P_FALSE(xdrs, p);
2001-05-23 15:26:42 +02:00
}
}
ULONG xdr_protocol_overhead(P_OP op)
{
/**************************************
*
* x d r _ p r o t o c o l _ o v e r h e a d
*
**************************************
*
* Functional description
* Report the overhead size of a particular packet.
* NOTE: This is not the same as the actual size to
* send the packet - as this figure discounts any data
* to be sent with the packet. It's purpose is to figure
* overhead for deciding on a batching window count.
*
* A better version of this routine would use xdr_sizeof - but
* it is unknown how portable that Solaris call is to other
* OS.
*
**************************************/
2009-04-16 08:52:08 +02:00
ULONG size = 4; // xdr_sizeof (xdr_enum, p->p_operation)
2001-05-23 15:26:42 +02:00
2009-01-16 10:55:38 +01:00
switch (op)
{
2001-05-23 15:26:42 +02:00
case op_fetch_response:
2009-04-16 08:52:08 +02:00
size += 4 // xdr_sizeof (xdr_long, sqldata->p_sqldata_status)
+ 4; // xdr_sizeof (xdr_short, sqldata->p_sqldata_messages)
2001-05-23 15:26:42 +02:00
break;
case op_send:
case op_start_and_send:
case op_start_send_and_receive:
2009-04-16 08:52:08 +02:00
size += 4 // xdr_sizeof (xdr_short, data->p_data_request)
+ 4 // xdr_sizeof (xdr_short, data->p_data_incarnation)
+ 4 // xdr_sizeof (xdr_short, data->p_data_transaction)
+ 4 // xdr_sizeof (xdr_short, data->p_data_message_number)
+ 4; // xdr_sizeof (xdr_short, data->p_data_messages)
2001-05-23 15:26:42 +02:00
break;
case op_response:
case op_response_piggyback:
2009-04-16 08:52:08 +02:00
// Note: minimal amounts are used for cstring & status_vector
size += 4 // xdr_sizeof (xdr_short, response->p_resp_object)
+ 8 // xdr_sizeof (xdr_quad, response->p_resp_blob_id)
+ 4 // xdr_sizeof (xdr_cstring, response->p_resp_data)
2001-05-23 15:26:42 +02:00
+
3 *
2009-04-16 08:52:08 +02:00
4; // xdr_sizeof (xdr_status_vector (xdrs, response->p_resp_status_vector
2001-05-23 15:26:42 +02:00
break;
default:
2009-04-16 08:52:08 +02:00
fb_assert(FALSE); // Not supported operation
2001-05-23 15:26:42 +02:00
return 0;
}
return size;
}
2009-01-16 10:55:38 +01:00
static bool alloc_cstring(XDR* xdrs, CSTRING* cstring)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* a l l o c _ c s t r i n g
*
**************************************
*
* Functional description
* Handle allocation for cstring.
*
**************************************/
if (!cstring->cstr_length)
2003-09-11 20:59:34 +02:00
return true;
2001-05-23 15:26:42 +02:00
2009-01-16 10:55:38 +01:00
if (cstring->cstr_length > cstring->cstr_allocated && cstring->cstr_allocated)
{
free_cstring(xdrs, cstring);
}
2001-05-23 15:26:42 +02:00
2009-01-16 10:55:38 +01:00
if (!cstring->cstr_address)
{
2003-11-04 00:59:24 +01:00
// fb_assert(!cstring->cstr_allocated);
try {
cstring->cstr_address = FB_NEW(*getDefaultMemoryPool()) UCHAR[cstring->cstr_length];
}
catch (const Firebird::BadAlloc&) {
2003-09-11 20:59:34 +02:00
return false;
}
2001-05-23 15:26:42 +02:00
cstring->cstr_allocated = cstring->cstr_length;
2009-01-16 10:55:38 +01:00
DEBUG_XDR_ALLOC(xdrs, cstring, cstring->cstr_address, cstring->cstr_allocated);
2001-05-23 15:26:42 +02:00
}
2003-09-11 20:59:34 +02:00
return true;
2001-05-23 15:26:42 +02:00
}
static void free_cstring( XDR* xdrs, CSTRING* cstring)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* f r e e _ c s t r i n g
*
**************************************
*
* Functional description
* Free any memory allocated for a cstring.
*
**************************************/
2009-06-28 12:26:25 +02:00
if (cstring->cstr_allocated)
{
delete[] cstring->cstr_address;
2009-01-16 10:55:38 +01:00
DEBUG_XDR_FREE(xdrs, cstring, cstring->cstr_address, cstring->cstr_allocated);
2001-05-23 15:26:42 +02:00
}
cstring->cstr_address = NULL;
cstring->cstr_allocated = 0;
}
// CVC: This function is a little stub to validate that indeed, bpb's aren't
// overwritten by accident. Even though xdr_string writes to cstr_address,
// an action we wanted to block, it first allocates a new buffer.
// The problem is that bpb's aren't copied, but referenced by address, so we
// don't want a const param being hijacked and its memory location overwritten.
// The same test has been applied to put_segment and batch_segments operations.
// The layout of CSTRING and CSTRING_CONST is exactly the same.
// Changing CSTRING to use cstr_address as const pointer would upset other
// places of the code, so only P_BLOB was changed to use CSTRING_CONST.
// The same function is being used to check P_SGMT & P_DDL.
static inline bool_t xdr_cstring_const(XDR* xdrs, CSTRING_CONST* cstring)
{
#ifdef SUPERCLIENT
#ifdef DEV_BUILD
const bool cond =
!(xdrs->x_op == XDR_DECODE &&
2008-12-31 06:06:08 +01:00
cstring->cstr_length <= cstring->cstr_allocated && cstring->cstr_allocated);
2003-11-04 00:59:24 +01:00
fb_assert(cond);
#endif
#endif
return xdr_cstring(xdrs, reinterpret_cast<CSTRING*>(cstring));
}
static bool_t xdr_cstring( XDR* xdrs, CSTRING* cstring)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* x d r _ c s t r i n g
*
**************************************
*
* Functional description
* Map a counted string structure.
*
**************************************/
SLONG l;
SCHAR trash[4];
2003-02-13 10:33:26 +01:00
static const SCHAR filler[4] = { 0, 0, 0, 0 };
2001-05-23 15:26:42 +02:00
2009-01-16 10:55:38 +01:00
if (!xdr_short(xdrs, reinterpret_cast<SSHORT*>(&cstring->cstr_length)))
{
return FALSE;
}
2001-05-23 15:26:42 +02:00
switch (xdrs->x_op)
{
2001-05-23 15:26:42 +02:00
case XDR_ENCODE:
if (cstring->cstr_length &&
!(*xdrs->x_ops->x_putbytes) (xdrs,
2009-01-16 10:55:38 +01:00
reinterpret_cast<const SCHAR*>(cstring->cstr_address),
2008-12-05 02:20:14 +01:00
cstring->cstr_length))
{
return FALSE;
}
2001-05-23 15:26:42 +02:00
l = (4 - cstring->cstr_length) & 3;
if (l)
2008-01-16 08:55:28 +01:00
return (*xdrs->x_ops->x_putbytes) (xdrs, filler, l);
return TRUE;
2001-05-23 15:26:42 +02:00
case XDR_DECODE:
if (!alloc_cstring(xdrs, cstring))
return FALSE;
2009-01-16 10:55:38 +01:00
if (!(*xdrs->x_ops->x_getbytes)(xdrs,
reinterpret_cast<SCHAR*>(cstring->cstr_address),
cstring->cstr_length))
{
return FALSE;
}
2001-05-23 15:26:42 +02:00
l = (4 - cstring->cstr_length) & 3;
if (l)
return (*xdrs->x_ops->x_getbytes) (xdrs, trash, l);
return TRUE;
case XDR_FREE:
free_cstring(xdrs, cstring);
return TRUE;
}
return FALSE;
}
2008-01-16 08:55:28 +01:00
static bool_t xdr_datum( XDR* xdrs, const DSC* desc, BLOB_PTR* buffer)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* x d r _ d a t u m
*
**************************************
*
* Functional description
* Handle a data item by relative descriptor and buffer.
*
**************************************/
BLOB_PTR* p = buffer + (IPTR) desc->dsc_address;
2001-05-23 15:26:42 +02:00
2009-01-16 10:55:38 +01:00
switch (desc->dsc_dtype)
{
2001-05-23 15:26:42 +02:00
case dtype_text:
2009-01-16 10:55:38 +01:00
if (!xdr_opaque(xdrs, reinterpret_cast<SCHAR*>(p), desc->dsc_length))
2004-09-22 10:49:50 +02:00
{
return FALSE;
}
2001-05-23 15:26:42 +02:00
break;
case dtype_varying:
{
2008-01-16 08:55:28 +01:00
fb_assert(desc->dsc_length >= sizeof(USHORT));
vary* v = reinterpret_cast<vary*>(p);
2009-01-16 10:55:38 +01:00
if (!xdr_short(xdrs, reinterpret_cast<SSHORT*>(&v->vary_length)))
2008-01-16 08:55:28 +01:00
{
return FALSE;
}
2009-01-16 10:55:38 +01:00
if (!xdr_opaque(xdrs, reinterpret_cast<SCHAR*>(v->vary_string),
MIN((USHORT) (desc->dsc_length - 2), v->vary_length)))
2008-01-16 08:55:28 +01:00
{
return FALSE;
}
}
2001-05-23 15:26:42 +02:00
break;
case dtype_cstring:
2008-01-16 08:55:28 +01:00
{
//SSHORT n;
USHORT n;
if (xdrs->x_op == XDR_ENCODE)
{
2009-01-16 10:55:38 +01:00
n = MIN(strlen(reinterpret_cast<char*>(p)), (ULONG) (desc->dsc_length - 1));
2008-01-16 08:55:28 +01:00
}
if (!xdr_short(xdrs, reinterpret_cast<SSHORT*>(&n)))
return FALSE;
if (!xdr_opaque(xdrs, reinterpret_cast<SCHAR*>(p), n))
return FALSE;
if (xdrs->x_op == XDR_DECODE)
p[n] = 0;
}
2001-05-23 15:26:42 +02:00
break;
case dtype_short:
2003-11-04 00:59:24 +01:00
fb_assert(desc->dsc_length >= sizeof(SSHORT));
2004-10-08 10:13:22 +02:00
if (!xdr_short(xdrs, reinterpret_cast<SSHORT*>(p)))
2001-05-23 15:26:42 +02:00
return FALSE;
break;
case dtype_sql_time:
case dtype_sql_date:
case dtype_long:
2003-11-04 00:59:24 +01:00
fb_assert(desc->dsc_length >= sizeof(SLONG));
2004-10-08 10:13:22 +02:00
if (!xdr_long(xdrs, reinterpret_cast<SLONG*>(p)))
2001-05-23 15:26:42 +02:00
return FALSE;
break;
case dtype_real:
2003-11-04 00:59:24 +01:00
fb_assert(desc->dsc_length >= sizeof(float));
2004-10-08 10:13:22 +02:00
if (!xdr_float(xdrs, reinterpret_cast<float*>(p)))
2008-01-16 08:55:28 +01:00
return FALSE;
2001-05-23 15:26:42 +02:00
break;
case dtype_double:
2003-11-04 00:59:24 +01:00
fb_assert(desc->dsc_length >= sizeof(double));
2004-10-08 10:13:22 +02:00
if (!xdr_double(xdrs, reinterpret_cast<double*>(p)))
2001-05-23 15:26:42 +02:00
return FALSE;
break;
case dtype_timestamp:
2003-11-04 00:59:24 +01:00
fb_assert(desc->dsc_length >= 2 * sizeof(SLONG));
2009-04-16 08:52:08 +02:00
if (!xdr_long(xdrs, &((SLONG*) p)[0]))
2001-05-23 15:26:42 +02:00
return FALSE;
2009-04-16 08:52:08 +02:00
if (!xdr_long(xdrs, &((SLONG*) p)[1]))
2001-05-23 15:26:42 +02:00
return FALSE;
break;
case dtype_int64:
2003-11-04 00:59:24 +01:00
fb_assert(desc->dsc_length >= sizeof(SINT64));
if (!xdr_hyper(xdrs, p))
2001-05-23 15:26:42 +02:00
return FALSE;
break;
case dtype_array:
case dtype_quad:
case dtype_blob:
2003-11-04 00:59:24 +01:00
fb_assert(desc->dsc_length >= sizeof(struct bid));
2009-04-16 08:52:08 +02:00
if (!xdr_quad(xdrs, (struct bid*) p))
2001-05-23 15:26:42 +02:00
return FALSE;
break;
default:
2003-11-04 00:59:24 +01:00
fb_assert(FALSE);
2001-05-23 15:26:42 +02:00
return FALSE;
}
return TRUE;
}
#ifdef DEBUG_XDR_MEMORY
static bool_t xdr_debug_packet( XDR* xdrs, enum xdr_op xop, PACKET* packet)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* x d r _ d e b u g _ p a c k e t
*
**************************************
*
* Functional description
* Start/stop monitoring a packet's memory allocations by
* entering/removing from a port's packet tracking vector.
*
**************************************/
rem_port* port = (rem_port*) xdrs->x_public;
2003-11-04 00:59:24 +01:00
fb_assert(port != 0);
fb_assert(port->port_header.blk_type == type_port);
2001-05-23 15:26:42 +02:00
2009-01-16 10:55:38 +01:00
if (xop == XDR_FREE)
{
2009-04-16 08:52:08 +02:00
// Free a slot in the packet tracking vector
2001-05-23 15:26:42 +02:00
rem_vec* vector = port->port_packet_vector;
if (vector)
2008-01-16 08:55:28 +01:00
{
2009-06-27 08:23:36 +02:00
for (ULONG i = 0; i < vector->vec_count; i++)
2008-01-16 08:55:28 +01:00
{
2001-05-23 15:26:42 +02:00
if (vector->vec_object[i] == (BLK) packet) {
vector->vec_object[i] = 0;
return TRUE;
}
2008-01-16 08:55:28 +01:00
}
}
2001-05-23 15:26:42 +02:00
}
else
2009-04-16 08:52:08 +02:00
{ // XDR_ENCODE or XDR_DECODE
2001-05-23 15:26:42 +02:00
2009-04-16 08:52:08 +02:00
// Allocate an unused slot in the packet tracking vector
// to start recording memory allocations for this packet.
2001-05-23 15:26:42 +02:00
2003-11-04 00:59:24 +01:00
fb_assert(xop == XDR_ENCODE || xop == XDR_DECODE);
rem_vec* vector = A L L R _vector(&port->port_packet_vector, 0);
2009-06-27 08:23:36 +02:00
ULONG i;
2001-05-23 15:26:42 +02:00
for (i = 0; i < vector->vec_count; i++)
2008-01-16 08:55:28 +01:00
{
2001-05-23 15:26:42 +02:00
if (vector->vec_object[i] == (BLK) packet)
return TRUE;
2008-01-16 08:55:28 +01:00
}
2001-05-23 15:26:42 +02:00
for (i = 0; i < vector->vec_count; i++)
2008-01-16 08:55:28 +01:00
{
2001-05-23 15:26:42 +02:00
if (vector->vec_object[i] == 0)
break;
2008-01-16 08:55:28 +01:00
}
2001-05-23 15:26:42 +02:00
if (i >= vector->vec_count)
vector = A L L R _vector(&port->port_packet_vector, i);
2001-05-23 15:26:42 +02:00
vector->vec_object[i] = (BLK) packet;
}
return TRUE;
}
#endif
static bool_t xdr_longs( XDR* xdrs, CSTRING* cstring)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* x d r _ l o n g s
*
**************************************
*
* Functional description
* Pass a vector of longs.
*
**************************************/
if (!xdr_short(xdrs, reinterpret_cast<SSHORT*>(&cstring->cstr_length)))
{
return FALSE;
}
2001-05-23 15:26:42 +02:00
2009-04-16 08:52:08 +02:00
// Handle operation specific stuff, particularly memory allocation/deallocation
2001-05-23 15:26:42 +02:00
2009-01-16 10:55:38 +01:00
switch (xdrs->x_op)
{
2001-05-23 15:26:42 +02:00
case XDR_ENCODE:
break;
case XDR_DECODE:
if (!alloc_cstring(xdrs, cstring))
return FALSE;
break;
case XDR_FREE:
free_cstring(xdrs, cstring);
return TRUE;
}
const ULONG n = cstring->cstr_length / sizeof(SLONG);
2001-05-23 15:26:42 +02:00
SLONG* next = (SLONG*) cstring->cstr_address;
for (const SLONG* const end = next + (int) n; next < end; next++)
{
2001-05-23 15:26:42 +02:00
if (!xdr_long(xdrs, next))
return FALSE;
}
2001-05-23 15:26:42 +02:00
return TRUE;
}
2009-01-16 10:55:38 +01:00
static bool_t xdr_message( XDR* xdrs, RMessage* message, const rem_fmt* format)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* x d r _ m e s s a g e
*
**************************************
*
* Functional description
* Map a formatted message.
*
**************************************/
if (xdrs->x_op == XDR_FREE)
return TRUE;
2008-01-16 08:55:28 +01:00
const rem_port* port = (rem_port*) xdrs->x_public;
2001-05-23 15:26:42 +02:00
2009-04-16 08:52:08 +02:00
// If we are running a symmetric version of the protocol, just slop
// the bits and don't sweat the translations
2001-05-23 15:26:42 +02:00
if (port->port_flags & PORT_symmetric)
2008-01-16 08:55:28 +01:00
{
return xdr_opaque(xdrs, reinterpret_cast<SCHAR*>(message->msg_address), format->fmt_length);
2008-01-16 08:55:28 +01:00
}
2001-05-23 15:26:42 +02:00
const dsc* desc = format->fmt_desc.begin();
for (const dsc* const end = desc + format->fmt_count; desc < end; ++desc)
2008-01-16 08:55:28 +01:00
{
2001-05-23 15:26:42 +02:00
if (!xdr_datum(xdrs, desc, message->msg_address))
return FALSE;
2008-01-16 08:55:28 +01:00
}
2001-05-23 15:26:42 +02:00
2004-05-17 12:22:34 +02:00
DEBUG_PRINTSIZE(xdrs, op_void);
2001-05-23 15:26:42 +02:00
return TRUE;
}
static bool_t xdr_quad( XDR* xdrs, struct bid* ip)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* x d r _ q u a d
*
**************************************
*
* Functional description
* Map from external to internal representation (or vice versa).
* A "quad" is represented by two longs.
* Currently used only for blobs
*
**************************************/
switch (xdrs->x_op)
{
2001-05-23 15:26:42 +02:00
case XDR_ENCODE:
2008-12-31 06:06:08 +01:00
if ((*xdrs->x_ops->x_putlong) (xdrs, reinterpret_cast<SLONG*>(&ip->bid_quad_high)) &&
(*xdrs->x_ops->x_putlong) (xdrs, reinterpret_cast<SLONG*>(&ip->bid_quad_low)))
{
return TRUE;
}
2001-05-23 15:26:42 +02:00
return FALSE;
case XDR_DECODE:
if (!(*xdrs->x_ops->x_getlong)(xdrs, reinterpret_cast<SLONG*>(&ip->bid_quad_high)))
{
return FALSE;
}
2008-12-31 06:06:08 +01:00
return (*xdrs->x_ops->x_getlong) (xdrs, reinterpret_cast<SLONG*>(&ip->bid_quad_low));
2001-05-23 15:26:42 +02:00
case XDR_FREE:
return TRUE;
}
return FALSE;
}
2008-12-31 06:06:08 +01:00
static bool_t xdr_request(XDR* xdrs,
2001-05-23 15:26:42 +02:00
USHORT request_id,
USHORT message_number, USHORT incarnation)
{
/**************************************
*
* x d r _ r e q u e s t
*
**************************************
*
* Functional description
* Map a formatted message.
*
**************************************/
if (xdrs->x_op == XDR_FREE)
return TRUE;
rem_port* port = (rem_port*) xdrs->x_public;
if (request_id >= port->port_objects.getCount())
return FALSE;
Rrq* request = port->port_objects[request_id];
2001-05-23 15:26:42 +02:00
if (!request)
return FALSE;
if (incarnation && !(request = REMOTE_find_request(request, incarnation)))
return FALSE;
if (message_number > request->rrq_max_msg)
return FALSE;
Rrq::rrq_repeat* tail = &request->rrq_rpt[message_number];
2001-05-23 15:26:42 +02:00
2009-01-16 10:55:38 +01:00
RMessage* message = tail->rrq_xdr;
if (!message)
2001-05-23 15:26:42 +02:00
return FALSE;
tail->rrq_xdr = message->msg_next;
2008-01-16 08:55:28 +01:00
const rem_fmt* format = tail->rrq_format;
2001-05-23 15:26:42 +02:00
2009-04-16 08:52:08 +02:00
// Find the address of the record
2001-05-23 15:26:42 +02:00
if (!message->msg_address)
message->msg_address = message->msg_buffer;
return xdr_message(xdrs, message, format);
}
2009-04-28 15:08:04 +02:00
// Maybe it's better to take sdl_length into account?
static bool_t xdr_slice(XDR* xdrs, lstring* slice, /*USHORT sdl_length,*/ const UCHAR* sdl)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* x d r _ s l i c e
*
**************************************
*
* Functional description
* Move a slice of an array under
*
**************************************/
2004-10-08 10:13:22 +02:00
if (!xdr_long(xdrs, reinterpret_cast<SLONG*>(&slice->lstr_length)))
2001-05-23 15:26:42 +02:00
return FALSE;
2009-04-16 08:52:08 +02:00
// Handle operation specific stuff, particularly memory allocation/deallocation
2001-05-23 15:26:42 +02:00
2009-01-16 10:55:38 +01:00
switch (xdrs->x_op)
{
2001-05-23 15:26:42 +02:00
case XDR_ENCODE:
break;
case XDR_DECODE:
if (!slice->lstr_length)
return TRUE;
2009-01-16 10:55:38 +01:00
if (slice->lstr_length > slice->lstr_allocated && slice->lstr_allocated)
2004-09-22 10:49:50 +02:00
{
delete[] slice->lstr_address;
2004-05-17 12:22:34 +02:00
DEBUG_XDR_FREE(xdrs, slice, slice->lstr_address, slice->lstr_allocated);
2001-05-23 15:26:42 +02:00
slice->lstr_address = NULL;
}
2009-01-16 10:55:38 +01:00
if (!slice->lstr_address)
{
try {
slice->lstr_address = FB_NEW(*getDefaultMemoryPool()) UCHAR[slice->lstr_length];
}
catch (const Firebird::BadAlloc&) {
return false;
2004-09-22 10:49:50 +02:00
}
2001-05-23 15:26:42 +02:00
slice->lstr_allocated = slice->lstr_length;
DEBUG_XDR_ALLOC(xdrs, slice, slice->lstr_address, slice->lstr_allocated);
2001-05-23 15:26:42 +02:00
}
break;
case XDR_FREE:
if (slice->lstr_allocated) {
delete[] slice->lstr_address;
2004-05-17 12:22:34 +02:00
DEBUG_XDR_FREE(xdrs, slice, slice->lstr_address, slice->lstr_allocated);
2001-05-23 15:26:42 +02:00
}
slice->lstr_address = NULL;
slice->lstr_allocated = 0;
return TRUE;
}
2009-04-16 08:52:08 +02:00
// Get descriptor of array element
2001-05-23 15:26:42 +02:00
2004-09-22 10:49:50 +02:00
ISC_STATUS_ARRAY status_vector;
struct sdl_info info;
2001-05-23 15:26:42 +02:00
if (SDL_info(status_vector, sdl, &info, 0))
return FALSE;
2008-01-16 08:55:28 +01:00
const dsc* desc = &info.sdl_info_element;
const rem_port* port = (rem_port*) xdrs->x_public;
2009-04-16 08:52:08 +02:00
BLOB_PTR* p = (BLOB_PTR*) slice->lstr_address;
2004-09-22 10:49:50 +02:00
ULONG n;
2001-05-23 15:26:42 +02:00
2008-01-16 08:55:28 +01:00
if (port->port_flags & PORT_symmetric)
{
2009-01-16 10:55:38 +01:00
for (n = slice->lstr_length; n > MAX_OPAQUE; n -= MAX_OPAQUE, p += (int) MAX_OPAQUE)
{
2004-10-08 10:13:22 +02:00
if (!xdr_opaque (xdrs, reinterpret_cast<SCHAR*>(p), MAX_OPAQUE))
2004-05-17 12:22:34 +02:00
return FALSE;
}
2001-05-23 15:26:42 +02:00
if (n)
2004-10-08 10:13:22 +02:00
if (!xdr_opaque(xdrs, reinterpret_cast<SCHAR*>(p), n))
2001-05-23 15:26:42 +02:00
return FALSE;
}
2009-01-16 10:55:38 +01:00
else
{
2009-06-28 12:26:25 +02:00
for (n = 0; n < slice->lstr_length / desc->dsc_length; n++)
{
2001-05-23 15:26:42 +02:00
if (!xdr_datum(xdrs, desc, p))
return FALSE;
p = p + (ULONG) desc->dsc_length;
}
}
return TRUE;
}
2009-01-16 10:55:38 +01:00
static bool_t xdr_sql_blr(XDR* xdrs,
2001-05-23 15:26:42 +02:00
SLONG statement_id,
CSTRING* blr,
bool direction, SQL_STMT_TYPE stmt_type)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* x d r _ s q l _ b l r
*
**************************************
*
* Functional description
* Map an sql blr string. This work is necessary because
* we will use the blr to read data in the current packet.
*
**************************************/
if (!xdr_cstring(xdrs, blr))
return FALSE;
2009-04-16 08:52:08 +02:00
// We care about all receives and sends from fetch
2001-05-23 15:26:42 +02:00
if (xdrs->x_op == XDR_FREE)
return TRUE;
rem_port* port = (rem_port*) xdrs->x_public;
2008-03-30 11:38:24 +02:00
Rsr* statement;
2009-01-16 10:55:38 +01:00
if (statement_id >= 0)
{
if (static_cast<ULONG>(statement_id) >= port->port_objects.getCount())
return FALSE;
if (!(statement = port->port_objects[statement_id]))
2001-05-23 15:26:42 +02:00
return FALSE;
}
2009-06-28 12:26:25 +02:00
else
{
2001-05-23 15:26:42 +02:00
if (!(statement = port->port_statement))
statement = port->port_statement = new Rsr;
2001-05-23 15:26:42 +02:00
}
2009-06-28 12:26:25 +02:00
if ((xdrs->x_op == XDR_ENCODE) && !direction)
{
2001-05-23 15:26:42 +02:00
if (statement->rsr_bind_format)
statement->rsr_format = statement->rsr_bind_format;
return TRUE;
}
2009-04-16 08:52:08 +02:00
// Parse the blr describing the message.
2001-05-23 15:26:42 +02:00
2009-01-16 10:55:38 +01:00
rem_fmt** fmt_ptr = direction ? &statement->rsr_select_format : &statement->rsr_bind_format;
2001-05-23 15:26:42 +02:00
2009-01-16 10:55:38 +01:00
if (xdrs->x_op == XDR_DECODE)
{
2009-04-16 08:52:08 +02:00
// For an immediate statement, flush out any previous format information
// that might be hanging around from an earlier execution.
// For all statements, if we have new blr, flush out the format information
// for the old blr.
2008-12-31 06:06:08 +01:00
if (*fmt_ptr && ((stmt_type == TYPE_IMMEDIATE) || blr->cstr_length != 0))
2004-09-22 10:49:50 +02:00
{
delete *fmt_ptr;
2001-05-23 15:26:42 +02:00
*fmt_ptr = NULL;
}
2009-04-16 08:52:08 +02:00
// If we have BLR describing a new input/output message, get ready by
// setting up a format
2009-06-28 12:26:25 +02:00
if (blr->cstr_length)
{
2009-01-16 10:55:38 +01:00
RMessage* temp_msg = (RMessage*) PARSE_messages(blr->cstr_address, blr->cstr_length);
2009-06-28 12:26:25 +02:00
if (temp_msg != (RMessage*) -1)
{
*fmt_ptr = (rem_fmt*) temp_msg->msg_address;
delete temp_msg;
2001-05-23 15:26:42 +02:00
}
}
}
2009-04-16 08:52:08 +02:00
// If we know the length of the message, make sure there is a buffer
// large enough to hold it.
2001-05-23 15:26:42 +02:00
if (!(statement->rsr_format = *fmt_ptr))
return TRUE;
2009-01-16 10:55:38 +01:00
RMessage* message = statement->rsr_buffer;
2008-03-30 22:43:36 +02:00
if (!message || statement->rsr_format->fmt_length > statement->rsr_fmt_length)
2004-09-22 10:49:50 +02:00
{
2001-05-23 15:26:42 +02:00
REMOTE_release_messages(message);
statement->rsr_fmt_length = statement->rsr_format->fmt_length;
2009-01-16 10:55:38 +01:00
statement->rsr_buffer = message = new RMessage(statement->rsr_fmt_length);
2001-05-23 15:26:42 +02:00
statement->rsr_message = message;
message->msg_next = message;
#ifdef SCROLLABLE_CURSORS
message->msg_prior = message;
#endif
}
return TRUE;
}
static bool_t xdr_sql_message( XDR* xdrs, SLONG statement_id)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* x d r _ s q l _ m e s s a g e
*
**************************************
*
* Functional description
* Map a formatted sql message.
*
**************************************/
2008-03-30 11:38:24 +02:00
Rsr* statement;
2001-05-23 15:26:42 +02:00
if (xdrs->x_op == XDR_FREE)
return TRUE;
rem_port* port = (rem_port*) xdrs->x_public;
2009-06-28 12:26:25 +02:00
if (statement_id >= 0)
{
if (static_cast<ULONG>(statement_id) >= port->port_objects.getCount())
2008-01-09 11:20:57 +01:00
return FALSE;
statement = port->port_objects[statement_id];
2001-05-23 15:26:42 +02:00
}
else
statement = port->port_statement;
if (!statement)
return FALSE;
2009-01-16 10:55:38 +01:00
RMessage* message = statement->rsr_buffer;
2009-06-28 12:26:25 +02:00
if (message)
{
2001-05-23 15:26:42 +02:00
statement->rsr_buffer = message->msg_next;
if (!message->msg_address)
message->msg_address = message->msg_buffer;
}
return xdr_message(xdrs, message, statement->rsr_format);
}
2009-01-16 10:55:38 +01:00
static bool_t xdr_status_vector(XDR* xdrs, ISC_STATUS* vector, TEXT* strings[])
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* x d r _ s t a t u s _ v e c t o r
*
**************************************
*
* Functional description
* Map a status vector. This is tricky since the status vector
* may contain argument types, numbers, and strings.
*
**************************************/
2009-04-16 08:52:08 +02:00
// If this is a free operation, release any allocated strings
2001-05-23 15:26:42 +02:00
2009-01-16 10:55:38 +01:00
if (xdrs->x_op == XDR_FREE)
{
2008-01-16 08:55:28 +01:00
TEXT **sp, **end;
2001-05-23 15:26:42 +02:00
for (sp = strings, end = strings + 10; sp < end; sp++)
2008-01-16 08:55:28 +01:00
{
2001-05-23 15:26:42 +02:00
if (*sp && !xdr_wrapstring(xdrs, sp))
return FALSE;
2008-01-16 08:55:28 +01:00
}
2001-05-23 15:26:42 +02:00
return TRUE;
}
2008-01-16 08:55:28 +01:00
SLONG vec;
XDR temp_xdrs;
2008-12-05 02:20:14 +01:00
2009-01-16 10:55:38 +01:00
while (true)
{
2001-05-23 15:26:42 +02:00
if (xdrs->x_op == XDR_ENCODE)
vec = (SLONG) * vector++;
if (!xdr_long(xdrs, &vec))
return FALSE;
if (xdrs->x_op == XDR_DECODE)
2003-04-10 12:31:28 +02:00
*vector++ = (ISC_STATUS) vec;
2008-12-05 02:20:14 +01:00
2008-01-16 08:55:28 +01:00
switch ((USHORT) vec)
{
case isc_arg_end:
2001-05-23 15:26:42 +02:00
return TRUE;
case isc_arg_interpreted:
case isc_arg_string:
case isc_arg_sql_state:
2009-06-28 12:26:25 +02:00
if (xdrs->x_op == XDR_ENCODE)
{
2006-04-09 08:46:28 +02:00
if (!xdr_wrapstring(xdrs, reinterpret_cast<SCHAR**>(vector++)))
2001-05-23 15:26:42 +02:00
return FALSE;
}
2009-01-16 10:55:38 +01:00
else
{
2009-04-16 08:52:08 +02:00
// Use the first slot in the strings table
2008-01-16 08:55:28 +01:00
TEXT** sp = strings;
2009-01-16 10:55:38 +01:00
if (*sp)
{
2009-04-16 08:52:08 +02:00
// Slot is used, by a string passed in a previous
// status vector. Free that string, and allocate
// a new one to prevent any size mismatches trashing
// memory.
2001-05-23 15:26:42 +02:00
temp_xdrs.x_public = xdrs->x_public;
temp_xdrs.x_op = XDR_FREE;
if (!xdr_wrapstring(&temp_xdrs, sp))
return FALSE;
*sp = NULL;
}
if (!xdr_wrapstring(xdrs, sp))
return FALSE;
2003-04-10 12:31:28 +02:00
*vector++ = (ISC_STATUS) * sp;
2001-05-23 15:26:42 +02:00
strings++;
}
break;
case isc_arg_number:
2001-05-23 15:26:42 +02:00
default:
if (xdrs->x_op == XDR_ENCODE)
vec = (SLONG) * vector++;
if (!xdr_long(xdrs, &vec))
return FALSE;
if (xdrs->x_op == XDR_DECODE)
2003-04-10 12:31:28 +02:00
*vector++ = (ISC_STATUS) vec;
2001-05-23 15:26:42 +02:00
break;
}
}
}
static bool_t xdr_trrq_blr(XDR* xdrs, CSTRING* blr)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* x d r _ t r r q _ b l r
*
**************************************
*
* Functional description
* Map a message blr string. This work is necessary because
* we will use the blr to read data in the current packet.
*
**************************************/
if (!xdr_cstring(xdrs, blr))
return FALSE;
2009-04-16 08:52:08 +02:00
// We care about all receives and sends from fetch
2001-05-23 15:26:42 +02:00
if (xdrs->x_op == XDR_FREE || xdrs->x_op == XDR_ENCODE)
return TRUE;
rem_port* port = (rem_port*) xdrs->x_public;
Rpr* procedure = port->port_rpr;
if (!procedure)
procedure = port->port_rpr = new Rpr;
2001-05-23 15:26:42 +02:00
2009-04-16 08:52:08 +02:00
// Parse the blr describing the message.
2001-05-23 15:26:42 +02:00
delete procedure->rpr_in_msg;
procedure->rpr_in_msg = NULL;
delete procedure->rpr_in_format;
procedure->rpr_in_format = NULL;
delete procedure->rpr_out_msg;
procedure->rpr_out_msg = NULL;
delete procedure->rpr_out_format;
procedure->rpr_out_format = NULL;
2008-12-05 02:20:14 +01:00
2009-01-16 10:55:38 +01:00
RMessage* message = PARSE_messages(blr->cstr_address, blr->cstr_length);
if (message != (RMessage*) -1)
{
while (message)
{
2008-01-16 08:55:28 +01:00
switch (message->msg_number)
{
case 0:
2001-05-23 15:26:42 +02:00
procedure->rpr_in_msg = message;
procedure->rpr_in_format = (rem_fmt*) message->msg_address;
2001-05-23 15:26:42 +02:00
message->msg_address = message->msg_buffer;
message = message->msg_next;
procedure->rpr_in_msg->msg_next = NULL;
2008-01-16 08:55:28 +01:00
break;
case 1:
2001-05-23 15:26:42 +02:00
procedure->rpr_out_msg = message;
procedure->rpr_out_format = (rem_fmt*) message->msg_address;
2001-05-23 15:26:42 +02:00
message->msg_address = message->msg_buffer;
message = message->msg_next;
procedure->rpr_out_msg->msg_next = NULL;
2008-01-16 08:55:28 +01:00
break;
default:
{
2009-01-16 10:55:38 +01:00
RMessage* temp = message;
2008-01-16 08:55:28 +01:00
message = message->msg_next;
delete temp;
2008-01-16 08:55:28 +01:00
}
break;
2001-05-23 15:26:42 +02:00
}
}
}
else
2003-11-04 00:59:24 +01:00
fb_assert(FALSE);
2001-05-23 15:26:42 +02:00
return TRUE;
}
static bool_t xdr_trrq_message( XDR* xdrs, USHORT msg_type)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* x d r _ t r r q _ m e s s a g e
*
**************************************
*
* Functional description
* Map a formatted transact request message.
*
**************************************/
if (xdrs->x_op == XDR_FREE)
return TRUE;
rem_port* port = (rem_port*) xdrs->x_public;
Rpr* procedure = port->port_rpr;
2001-05-23 15:26:42 +02:00
if (msg_type == 1)
2009-01-16 10:55:38 +01:00
return xdr_message(xdrs, procedure->rpr_out_msg, procedure->rpr_out_format);
2008-01-16 08:55:28 +01:00
2009-01-16 10:55:38 +01:00
return xdr_message(xdrs, procedure->rpr_in_msg, procedure->rpr_in_format);
2001-05-23 15:26:42 +02:00
}
2009-04-16 08:52:08 +02:00
static Rsr* get_statement( XDR* xdrs, SSHORT statement_id)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* g e t _ s t a t e m e n t
*
**************************************
*
* Functional description
* Returns the statement based upon the statement id
* if statement_id = -1 then statement = port_statement
* otherwise, the statement comes from port_objects[statement_id]
* if there are no port_objects, then statement = NULL
*
**************************************/
Rsr* statement = NULL;
rem_port* port = (rem_port*) xdrs->x_public;
2001-05-23 15:26:42 +02:00
2009-04-16 08:52:08 +02:00
// if the statement ID is -1, this seems to indicate that we are
// re-executing the previous statement. This is not a
// well-understood area of the implementation.
2001-05-23 15:26:42 +02:00
2009-04-16 08:52:08 +02:00
//if (statement_id == -1)
// statement = port->port_statement;
//else
2001-05-23 15:26:42 +02:00
2003-11-04 00:59:24 +01:00
fb_assert(statement_id >= -1);
2001-05-23 15:26:42 +02:00
2008-03-26 03:37:14 +01:00
if (((ULONG) statement_id < port->port_objects.getCount()) && (statement_id >= 0))
2004-09-22 10:49:50 +02:00
{
statement = port->port_objects[statement_id];
2004-09-22 10:49:50 +02:00
}
2001-05-23 15:26:42 +02:00
return statement;
}