/* * PROGRAM: JRD Remote Interface/Server * MODULE: remote.h * DESCRIPTION: Common descriptions * * 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.10.29 Sean Leyne - Removed obsolete "Netware" port * * 2002.10.30 Sean Leyne - Removed support for obsolete "PC_PLATFORM" define * */ #ifndef REMOTE_REMOTE_H #define REMOTE_REMOTE_H #include "../jrd/common.h" #include "../remote/remote_def.h" #include "../jrd/thd.h" #include "../common/classes/objects_array.h" #include "../auth/trusted/AuthSspi.h" #include "../common/classes/fb_string.h" #include "../common/classes/ClumpletWriter.h" /* Include some apollo include files for tasking */ #if !(defined VMS || defined WIN_NT) #include #include #include #include #endif /* !VMS || !WIN_NT */ // Uncomment this line if you need to trace module activity //#define REMOTE_DEBUG #ifdef REMOTE_DEBUG DEFINE_TRACE_ROUTINE(remote_trace); #define REMOTE_TRACE(args) remote_trace args #else #define REMOTE_TRACE(args) /* nothing */ #endif #ifdef DEV_BUILD /* Debug packet/XDR memory allocation */ /* Temporarily disabling DEBUG_XDR_MEMORY */ /* #define DEBUG_XDR_MEMORY */ #endif const int BLOB_LENGTH = 16384; #include "../remote/protocol.h" /* Block types */ struct blk; #ifndef INCLUDE_FB_BLK #include "../include/old_fb_blk.h" #endif // fwd. decl. struct rem_port; typedef struct rdb { blk rdb_header; USHORT rdb_id; USHORT rdb_flags; FB_API_HANDLE rdb_handle; /* database handle */ rem_port* rdb_port; /* communication port */ struct rtr* rdb_transactions; /* linked list of transactions */ struct rrq* rdb_requests; /* compiled requests */ struct rvnt* rdb_events; /* known events */ struct rsr* rdb_sql_requests; /* SQL requests */ ISC_STATUS* rdb_status_vector; PACKET rdb_packet; /* Communication structure */ } *RDB; // rdb_flags const USHORT RDB_service = 1; /* structure relates to a service */ typedef struct rtr { blk rtr_header; rdb* rtr_rdb; rtr* rtr_next; struct rbl* rtr_blobs; FB_API_HANDLE rtr_handle; USHORT rtr_flags; USHORT rtr_id; } *RTR; // rtr_flags const USHORT RTR_limbo = 1; typedef struct rbl { blk rbl_header; rdb* rbl_rdb; rtr* rbl_rtr; rbl* rbl_next; FB_API_HANDLE rbl_handle; SLONG rbl_offset; /* Apparent (to user) offset in blob */ USHORT rbl_id; USHORT rbl_flags; UCHAR* rbl_ptr; UCHAR* rbl_buffer; USHORT rbl_buffer_length; USHORT rbl_length; USHORT rbl_fragment_length; USHORT rbl_source_interp; /* source interp (for writing) */ USHORT rbl_target_interp; /* destination interp (for reading) */ UCHAR rbl_data[1]; } *RBL; // rbl_flags const USHORT RBL_eof = 1; const USHORT RBL_segment = 2; const USHORT RBL_eof_pending= 4; const USHORT RBL_create = 8; typedef struct rvnt { blk rvnt_header; rvnt* rvnt_next; rdb* rvnt_rdb; FPTR_EVENT_CALLBACK rvnt_ast; void* rvnt_arg; SLONG rvnt_id; SLONG rvnt_rid; /* used by server to store client-side id */ rem_port* rvnt_port; /* used to id server from whence async came */ const UCHAR* rvnt_items; SSHORT rvnt_length; } *RVNT; struct rem_vec { blk vec_header; ULONG vec_count; blk* vec_object[1]; }; //struct rem_vcl //{ // blk vcl_header; // ULONG vcl_count; // SLONG vcl_long[1]; //}; /* Random string block -- jack of all kludges */ struct rem_str { blk str_header; USHORT str_length; SCHAR str_data[2]; }; /* Include definition of descriptor */ #include "../jrd/dsc.h" struct rem_fmt { blk fmt_header; USHORT fmt_length; USHORT fmt_net_length; USHORT fmt_count; USHORT fmt_version; USHORT fmt_flags; // unused struct dsc fmt_desc[1]; }; // fmt_flags (not used) //#define FMT_has_P10_specific_datatypes 0x1 /* datatypes don't exist in P9 */ /* Windows declares a msg structure, so rename the structure to avoid overlap problems. */ typedef struct message { blk msg_header; message* msg_next; /* Next available message */ #ifdef SCROLLABLE_CURSORS message* msg_prior; /* Next available message */ ULONG msg_absolute; /* Absolute record number in cursor result set */ #endif /* Please DO NOT re-arrange the order of following two fields. This could result in alignment problems while trying to access 'msg_buffer' as a 'long', leading to "core" drops Sriram - 04-Jun-97 */ USHORT msg_number; /* Message number */ UCHAR* msg_address; /* Address of message */ UCHAR msg_buffer[1]; /* Allocated message */ } *REM_MSG; /* remote stored procedure request */ typedef struct rpr { blk rpr_header; rdb* rpr_rdb; rtr* rpr_rtr; FB_API_HANDLE rpr_handle; message* rpr_in_msg; /* input message */ message* rpr_out_msg; /* output message */ rem_fmt* rpr_in_format; /* Format of input message */ rem_fmt* rpr_out_format; /* Format of output message */ USHORT rpr_flags; // unused } *RPR; // rpr_flags (not used) //#define RPR_eof 1 /* End-of-stream encountered */ struct rrq { blk rrq_header; rdb* rrq_rdb; rtr* rrq_rtr; rrq* rrq_next; rrq* rrq_levels; /* RRQ block for next level */ FB_API_HANDLE rrq_handle; USHORT rrq_id; USHORT rrq_max_msg; USHORT rrq_level; ISC_STATUS_ARRAY rrq_status_vector; struct rrq_repeat { rem_fmt* rrq_format; /* format for this message */ message* rrq_message; /* beginning or end of cache, depending on whether it is client or server */ message* rrq_xdr; /* point at which cache is read or written by xdr */ #ifdef SCROLLABLE_CURSORS message* rrq_last; /* last message returned */ ULONG rrq_absolute; /* current offset in result set for record being read into cache */ USHORT rrq_flags; #endif USHORT rrq_msgs_waiting; /* count of full rrq_messages */ USHORT rrq_rows_pending; /* How many rows in waiting */ USHORT rrq_reorder_level; /* Reorder when rows_pending < this level */ USHORT rrq_batch_count; /* Count of batches in pipeline */ } rrq_rpt[1]; }; // rrq_flags #ifdef SCROLLABLE_CURSORS const USHORT RRQ_backward = 1; /* the cache was created in the backward direction */ const USHORT RRQ_absolute_backward = 2; /* rrq_absolute is measured from the end of the stream */ const USHORT RRQ_last_backward = 4; /* last time, the next level up asked for us to scroll in the backward direction */ #endif /* remote SQL request */ typedef struct rsr { blk rsr_header; rsr* rsr_next; rdb* rsr_rdb; rtr* rsr_rtr; FB_API_HANDLE rsr_handle; rem_fmt* rsr_bind_format; /* Format of bind message */ rem_fmt* rsr_select_format; /* Format of select message */ rem_fmt* rsr_user_select_format; /* Format of user's select message */ rem_fmt* rsr_format; /* Format of current message */ message* rsr_message; /* Next message to process */ message* rsr_buffer; /* Next buffer to use */ ISC_STATUS_ARRAY rsr_status_vector; /* saved status for buffered errors */ USHORT rsr_id; USHORT rsr_flags; USHORT rsr_fmt_length; ULONG rsr_rows_pending; /* How many rows are pending */ USHORT rsr_msgs_waiting; /* count of full rsr_messages */ USHORT rsr_reorder_level; /* Trigger pipelining at this level */ USHORT rsr_batch_count; /* Count of batches in pipeline */ } *RSR; // rsr_flags const USHORT RSR_fetched = 1; /* Cleared by execute, set by fetch */ const USHORT RSR_eof = 2; /* End-of-stream encountered */ const USHORT RSR_blob = 4; /* Statement relates to blob op */ const USHORT RSR_no_batch = 8; /* Do not batch fetch rows */ const USHORT RSR_stream_err = 16; /* There is an error pending in the batched rows */ const USHORT RSR_lazy = 32; /* To be allocated at the first reference */ enum blk_t { type_MIN = 0, type_vec, type_rdb, type_fmt, type_rrq, type_rtr, type_str, type_rbl, type_port, type_msg, type_rsr, type_rvnt, type_rpr, type_rmtque, type_MAX }; #include "../remote/xdr.h" /* Generalized port definition. */ enum rem_port_t { port_inet, /* Internet (TCP/IP) */ port_pipe, /* Windows NT named pipe connection */ port_xnet /* Windows NT shared memory connection */ }; enum state_t { state_closed, /* no connection */ state_pending, /* connection is pending */ state_eof, /* other side has shut down */ state_broken, /* connection is broken */ state_active, /* connection is complete */ state_disconnected /* port is disconnected */ }; #ifndef WIN_NT typedef int HANDLE; #endif /* WIN_NT */ ////////////////////////////////////////////////////////////////// // fwd. decl. struct p_cnct; struct rmtque; /* Queue of deferred packets */ struct rem_que_packet { PACKET packet; bool sent; }; typedef Firebird::Array PacketQueue; #ifdef TRUSTED_AUTH // delayed authentication block for trusted auth callback class ServerAuth { public: typedef void Part2(rem_port*, P_OP, const char* fName, int fLen, const UCHAR* pb, int pbLen, PACKET*); Firebird::PathName fileName; Firebird::HalfStaticArray clumplet; AuthSspi* authSspi; Part2* part2; P_OP operation; ServerAuth(const char* fName, int fLen, const Firebird::ClumpletWriter& pb, Part2* p2, P_OP op); ~ServerAuth(); }; #endif //TRUSTED_AUTH /* Port itself */ class port_interface { public: virtual int accept_(rem_port* pPort, p_cnct* pConnection) = 0; }; //typedef XDR_INT (*t_event_ast)(); typedef void (*t_event_ast)(rem_port*); typedef rem_port* (*t_port_connect)(rem_port*, PACKET*, t_event_ast); struct rem_port { blk port_header; enum rem_port_t port_type; /* type of port */ enum state_t port_state; /* state of port */ P_ARCH port_client_arch; /* so we can tell arch of client */ rem_port* port_clients; /* client ports */ rem_port* port_next; /* next client port */ rem_port* port_parent; /* parent port (for client ports) */ rem_port* port_async; /* asynchronous sibling port */ struct srvr* port_server; /* server of port */ USHORT port_server_flags; /* TRUE if server */ USHORT port_protocol; /* protocol version number */ USHORT port_buff_size; /* port buffer size (approx) */ USHORT port_flags; /* Misc flags */ SLONG port_connect_timeout; /* Connection timeout value */ SLONG port_dummy_packet_interval; /* keep alive dummy packet interval */ SLONG port_dummy_timeout; /* time remaining until keepalive packet */ ISC_STATUS* port_status_vector; HANDLE port_handle; /* handle for connection (from by OS) */ int port_channel; /* handle for connection (from by OS) */ int port_misc1; SLONG port_semaphore; struct linger port_linger; /* linger value as defined by SO_LINGER */ /* port function pointers (C "emulation" of virtual functions) */ int (*port_accept)(rem_port*, p_cnct*); void (*port_disconnect)(rem_port*); rem_port* (*port_receive_packet)(rem_port*, PACKET*); XDR_INT (*port_send_packet)(rem_port*, PACKET*); XDR_INT (*port_send_partial)(rem_port*, PACKET*); t_port_connect port_connect; /* Establish secondary connection */ rem_port* (*port_request)(rem_port*, PACKET*); /* Request to establish secondary connection */ rem_port* (*port_select_multi)(rem_port*, UCHAR*, SSHORT, SSHORT*); // get packet from active port rdb* port_context; t_event_ast port_ast; /* AST for events */ XDR port_receive; XDR port_send; #ifdef DEBUG_XDR_MEMORY rem_vec* port_packet_vector; /* Vector of send/receive packets */ #endif rem_vec* port_object_vector; BLK* port_objects; rem_str* port_version; rem_str* port_host; /* Our name */ rem_str* port_connection; /* Name of connection */ rem_str* port_user_name; rem_str* port_passwd; rem_str* port_protocol_str; // String containing protocol name for this port rem_str* port_address_str; // Protocol-specific address string for the port rpr* port_rpr; /* port stored procedure reference */ rsr* port_statement; /* Statement for execute immediate */ rmtque* port_receive_rmtque; /* for client, responses waiting */ USHORT port_requests_queued; /* requests currently queued */ #ifdef VMS USHORT port_iosb[4]; #endif void* port_xcc; /* interprocess structure */ PacketQueue* port_deferred_packets; /* queue of deferred packets */ OBJCT port_last_object_id; /* cached last id */ #ifdef SUPERSERVER Firebird::ObjectsArray< Firebird::Array< char > >* port_queue; size_t port_qoffset; // current packet in the queue #endif #ifdef TRUSTED_AUTH ServerAuth* port_trusted_auth; #endif UCHAR port_buffer[1]; /* TMN: Beginning of C++ port */ /* TMN: ugly, but at least a start */ int accept(p_cnct* cnct); void disconnect(); rem_port* receive(PACKET* pckt); XDR_INT send(PACKET* pckt); XDR_INT send_partial(PACKET* pckt); rem_port* connect(PACKET* pckt, t_event_ast); rem_port* request(PACKET* pckt); rem_port* select_multi(UCHAR* buffer, SSHORT bufsize, SSHORT* length); /* TMN: The following member functions are conceptually private * to server.cpp and should be _made_ private in due time! * That is, if we don't factor these method out. */ ISC_STATUS compile(P_CMPL*, PACKET*); ISC_STATUS ddl(P_DDL*, PACKET*); void disconnect(PACKET*, PACKET*); void drop_database(P_RLSE*, PACKET*); ISC_STATUS end_blob(P_OP, P_RLSE*, PACKET*); ISC_STATUS end_database(P_RLSE*, PACKET*); ISC_STATUS end_request(P_RLSE*, PACKET*); ISC_STATUS end_statement(P_SQLFREE*, PACKET*); ISC_STATUS end_transaction(P_OP, P_RLSE*, PACKET*); ISC_STATUS execute_immediate(P_OP, P_SQLST*, PACKET*); ISC_STATUS execute_statement(P_OP, P_SQLDATA*, PACKET*); ISC_STATUS fetch(P_SQLDATA*, PACKET*); ISC_STATUS fetch_blob(P_SQLDATA*, PACKET*); OBJCT get_id(BLK); ISC_STATUS get_segment(P_SGMT*, PACKET*); ISC_STATUS get_slice(P_SLC*, PACKET*); ISC_STATUS info(P_OP, P_INFO*, PACKET*); ISC_STATUS insert(P_SQLDATA*, PACKET*); ISC_STATUS open_blob(P_OP, P_BLOB*, PACKET*); ISC_STATUS prepare(P_PREP*, PACKET*); ISC_STATUS prepare_statement(P_SQLST*, PACKET*); ISC_STATUS put_segment(P_OP, P_SGMT*, PACKET*); ISC_STATUS put_slice(P_SLC*, PACKET*); ISC_STATUS que_events(P_EVENT*, PACKET*); ISC_STATUS receive_after_start(P_DATA*, PACKET*, ISC_STATUS*); ISC_STATUS receive_msg(P_DATA*, PACKET*); ISC_STATUS seek_blob(P_SEEK*, PACKET*); ISC_STATUS send_msg(P_DATA*, PACKET*); ISC_STATUS send_response(PACKET*, OBJCT, USHORT, const ISC_STATUS*, bool); ISC_STATUS service_attach(const char*, const USHORT, Firebird::ClumpletWriter&, PACKET*); ISC_STATUS service_end(P_RLSE*, PACKET*); ISC_STATUS service_start(P_INFO*, PACKET*); ISC_STATUS set_cursor(P_SQLCUR*, PACKET*); ISC_STATUS start(P_OP, P_DATA*, PACKET*); ISC_STATUS start_and_send(P_OP, P_DATA*, PACKET*); ISC_STATUS start_transaction(P_OP, P_STTR*, PACKET*); ISC_STATUS transact_request(P_TRRQ *, PACKET*); }; // port_flags const USHORT PORT_symmetric = 1; /* Server/client archiectures are symmetic */ const USHORT PORT_rpc = 2; /* Protocol is remote procedure call */ const USHORT PORT_pend_ack = 4; /* An ACK is pending on the port */ const USHORT PORT_broken = 8; /* Connect is broken */ const USHORT PORT_async = 16; /* Port is asynchronous channel for events */ const USHORT PORT_no_oob = 32; /* Don't send out of band data */ const USHORT PORT_disconnect = 64; /* Disconnect is in progress */ //const USHORT PORT_pend_rec = 128; // A record is pending on the port // This is set only in inet.cpp but never tested. const USHORT PORT_not_trusted = 256; /* Connection is from an untrusted node */ // This is tested only in wnet.cpp but never set. //const USHORT PORT_impersonate = 512; // A remote user is being impersonated const USHORT PORT_dummy_pckt_set= 1024; /* A dummy packet interval is set */ const USHORT PORT_partial_data = 2048; /* Physical packet doesn't contain all API packet */ const USHORT PORT_lazy = 4096; /* Deferred operations are allowed */ /* Misc declarations */ #include "../remote/allr_proto.h" #include "../jrd/thd.h" /* Thread specific remote database block */ class trdb : public ThreadData { public: trdb(ISC_STATUS* status) : ThreadData(ThreadData::tddRDB), trdb_status_vector(status) { trdb_database = 0; } rdb* trdb_database; ISC_STATUS* trdb_status_vector; }; typedef trdb* TRDB; inline trdb* REM_get_thread_data() { return (trdb*) ThreadData::getSpecific(); } inline void REM_set_thread_data(trdb* &tdrdb, trdb* thd_context) { tdrdb = thd_context; tdrdb->putSpecific(); } inline void REM_restore_thread_data() { ThreadData::restoreSpecific(); } /* Queuing structure for Client batch fetches */ typedef bool (*t_rmtque_fn)(trdb*, rem_port*, rmtque*, ISC_STATUS*, USHORT); typedef struct rmtque { blk rmtque_header; // Memory allocator header rmtque* rmtque_next; // Next entry in queue void* rmtque_parm; // What request has response in queue rrq::rrq_repeat* rmtque_message; // What message is pending rdb* rmtque_rdb; // What database has pending msg /* Fn that receives queued entry */ t_rmtque_fn rmtque_function; } *RMTQUE; #endif // REMOTE_REMOTE_H