GCD_RCB * gcd_new_rcb( GCD_CCB *ccb, i2 len ) { GCD_RCB *rcb; /* ** Adjust length to reserve header space. ** ** The majority of RCB allocations are for default ** buffer sizes or no buffers. Re-use free RCB with ** same buffer size if available. */ if ( len == 0 ) rcb = (GCD_RCB *)QUremove( GCD_global.rcb_q.q_next ); else if ( len < 0 ) { /* ** Use the negotiated TL protocol buffer size from ** the CCB (TL header length already included) and ** provide space for the NL header. */ len = ccb->max_buff_len + (u_i2)GCD_global.nl_hdr_sz; rcb = (GCD_RCB *)QUremove( ccb->rcb_q.q_next ); } else { /* ** NL protocol restricts the size of buffers which ** may be sent. Provide space for TL header by ** increasing requested buffer length. Space is ** also provided for the NL header. */ len = min( len + (u_i2)GCD_global.tl_hdr_sz, ccb->max_buff_len ) + (u_i2)GCD_global.nl_hdr_sz; rcb = NULL; /* RCB must be allocated */ } if ( rcb ) MEfill( sizeof( GCD_RCB ), 0, rcb ); else { rcb = (GCD_RCB *)MEreqmem( 0, sizeof( GCD_RCB ) + len, TRUE, NULL ); if ( ! rcb ) { gcu_erlog( 0, GCD_global.language, E_GC4808_NO_MEMORY, NULL, 0, NULL ); return( NULL ); } if ( GCD_global.gcd_trace_level >= 6 ) TRdisplay( "%4d GCD new RCB[%d] (%p)\n", ccb->id, len, rcb ); } rcb->ccb = ccb; if ( len ) { rcb->buffer = (u_i1 *)rcb + sizeof( GCD_RCB ); rcb->buf_max = (u_i2)len; gcd_init_rcb( rcb ); } return( rcb ); }
static void dmtl_data( GCD_RCB *rcb ) { GCD_CCB *ccb = rcb->ccb; DAM_TL_HDR hdr; STATUS status = E_GC480A_PROTOCOL_ERROR; u_i2 pkt_type; /* ** Breaking from the switch will shutdown the connection. ** If status is not changed, connection will be aborted ** with protocol error (set to OK for simple shutdown). ** Set the rcb to NULL if not used for new request. ** ** Return directly in the switch for any other result ** (but make sure RCB is used or freed). */ switch( (pkt_type = read_hdr( rcb, &hdr )) ) { case DAM_TL_CR : case DAM_TL_CC : case DAM_TL_DC : /* ** The Connection Request packet is expected only ** initially and should be passed to dmtl_accept(). ** ** The Connection Confirm packet is never expected. ** ** We only send a Disconnect Request when aborting ** the connection and we don't wait for a response, ** so we don't expect a Disconnect Confirmation. */ if ( GCD_global.gcd_trace_level >= 1 ) TRdisplay( "%4d GCD unexpected DMTL packet: 0x%x\n", ccb->id, pkt_type ); break; case DAM_TL_DT : /* Data */ if ( ccb->tl.msg_service ) { if ( GCD_global.gcd_trace_level >= 3 ) TRdisplay( "%4d GCD DMTL received data\n", ccb->id ); /* ** Pass to MSG Layer and exit successfully. */ (*ccb->tl.msg_service->data)( rcb ); return; } break; case DAM_TL_INT: /* Interrupt */ if ( ccb->tl.msg_service ) { if ( GCD_global.gcd_trace_level >= 3 ) TRdisplay( "%4d GCD DMTL interrupt\n", ccb->id ); /* ** Notify MSG Layer and exit successfully. ** Need to free RCB as we are expected to ** consume the RCB. */ gcd_del_rcb( rcb ); (*ccb->tl.msg_service->intr)( ccb ); return; } break; case DAM_TL_DR : /* Disconnect */ if ( ccb->tl.gcc_service ) { if ( GCD_global.gcd_trace_level >= 3 ) TRdisplay( "%4d GCD DMTL disconnecting\n", ccb->id ); gcd_init_rcb( rcb ); hdr.msg_id = DAM_TL_DC; build_hdr( rcb, &hdr ); (*ccb->tl.gcc_service->send)( rcb ); rcb = NULL; /* Passed to GCC */ status = OK; /* Shutdown, don't abort */ } break; default : if ( GCD_global.gcd_trace_level >= 1 ) TRdisplay( "%4d GCD invalid DMTL packet: ID=0x%x Type=0x%x\n", ccb->id, hdr.tl_id, hdr.msg_id ); break; } dmtl_shutdown( ccb, rcb, status ); return; }
static void send_dr( GCD_CCB *ccb, GCD_RCB *rcb, STATUS error ) { DAM_TL_HDR hdr; if ( ! ccb->tl.gcc_service ) /* Already shutdown? */ { /* ** Consume RCB if provided. */ if ( rcb ) gcd_del_rcb( rcb ); return; } if ( GCD_global.gcd_trace_level >= 3 ) TRdisplay( "%4d GCD DMTL aborting connection: 0x%x\n", ccb->id, error ); /* ** If RCB provided, initialize since it may ** have contained data. Allocate otherwise. ** Allow room for error parameter. */ if ( rcb ) gcd_init_rcb( rcb ); else if ( ! (rcb = gcd_new_rcb( ccb, (CV_N_I1_SZ * 2) + CV_N_I4_SZ )) ) return; /* ** Return error code to client when provided. */ if ( error != OK && error != FAIL ) { DAM_TL_PARAM param; STATUS status; param.param_id = DAM_TL_DP_ERR; CV2N_I1_MACRO( ¶m.param_id, &rcb->buf_ptr[ rcb->buf_len ], &status ); rcb->buf_len += CV_N_I1_SZ; param.pl1 = CV_N_I4_SZ; CV2N_I1_MACRO( ¶m.pl1, &rcb->buf_ptr[ rcb->buf_len ], &status ); rcb->buf_len += CV_N_I1_SZ; CV2N_I4_MACRO( &error, &rcb->buf_ptr[ rcb->buf_len ], &status ); rcb->buf_len += CV_N_I4_SZ; } /* ** Add TL packet header and send packet. */ hdr.tl_id = ccb->tl.packet_id; hdr.msg_id = DAM_TL_DR; build_hdr( rcb, &hdr ); (*ccb->tl.gcc_service->send)( rcb ); return; }
static bool dmtl_accept( GCC_SRVC *gcc_service, GCD_RCB *rcb ) { GCD_CCB *ccb = rcb->ccb; DAM_TL_HDR hdr; STATUS status = OK; u_i1 *rcb_ptr; u_i4 rcb_len; u_i1 *msg_parms = NULL; u_i2 msg_len = 0; u_i1 size = DAM_TL_PKT_MIN; if ( GCD_global.gcd_trace_level >= 4 ) TRdisplay( "%4d GCD DMTL testing new connection\n", ccb->id ); /* ** Save RCB settings in case we don't accept ** the connection and need to restore the RCB. */ rcb_ptr = rcb->buf_ptr; rcb_len = rcb->buf_len; /* ** Validate the packet header and request type. ** If invalid, refuse GCC request. We accept ** both the JDBC TL and DAM-TL packet ID's for ** now. The protocol level parameter will tell ** which TL should handle this request. */ read_hdr( rcb, &hdr ); if ( (hdr.tl_id != DAM_TL_ID_1 && hdr.tl_id != DAM_TL_ID_2) || hdr.msg_id != DAM_TL_CR ) { rcb->buf_ptr = rcb_ptr; rcb->buf_len = rcb_len; return( FALSE ); } /* ** Read the TL Connection Request parameters. ** ** The DAM-TL protocol is a super-set of the JDBC TL ** protocol. We should be able to read JDBC connect ** parms, so if there is an error we will accept the ** GCC connection and then abort the TL connection. ** ** We refuse the connection if the protocol level and ** packet header ID indicate that this is for JDBC TL. */ if ( (status = read_cr_parms( rcb, &size, &msg_parms, &msg_len )) == OK && hdr.tl_id == DAM_TL_ID_1 && ccb->tl.proto_lvl < DAM_TL_PROTO_2 ) { rcb->buf_ptr = rcb_ptr; rcb->buf_len = rcb_len; return( FALSE ); } /* ** We will service this connection from GCC, ** though we may detect an error and abort ** the client connection. ** ** We must respond to this request with the ** same TL packet ID as the original request. ** Subsequent packets must have the packet ** ID appropriate for the protocol level. */ if ( GCD_global.gcd_trace_level >= 4 ) TRdisplay( "%4d GCD DMTL servicing request\n", ccb->id ); ccb->tl.gcc_service = gcc_service; ccb->tl.packet_id = hdr.tl_id; /* ** Validate connection parameters. */ for( ; status == OK; ) { if ( ccb->tl.proto_lvl < DAM_TL_PROTO_1 || size < DAM_TL_PKT_MIN ) { if ( GCD_global.gcd_trace_level >= 1 ) TRdisplay( "%4d GCD invalid param value: (%d,%d)\n", ccb->id, ccb->tl.proto_lvl, size ); status = E_GC480A_PROTOCOL_ERROR; break; } /* ** Negotiate connection parameters. */ if ( ccb->tl.proto_lvl > DAM_TL_DFLT_PROTO ) ccb->tl.proto_lvl = DAM_TL_DFLT_PROTO; if ( size > DAM_TL_PKT_DEF ) size = DAM_TL_PKT_DEF; ccb->max_buff_len = 1 << size; if ( GCD_global.gcd_trace_level >= 4 ) { TRdisplay( "%4d protocol level: %d\n", ccb->id, ccb->tl.proto_lvl ); TRdisplay( "%4d buffer size: %d\n", ccb->id, ccb->max_buff_len ); } /* ** Initialize our MSG Service Provider. */ if ( (status = (*gcd_dam_service.init)( &dmtl_msg_service, ccb, &msg_parms, &msg_len )) != OK ) break; /* ** OK, we are ready to accept the connection. Inform the GCC ** Service provider and verify that the connection should be ** accepted. */ ccb->tl.msg_service = &gcd_dam_service; status = (*gcc_service->accept)( &gcd_dmtl_service, ccb ); break; } if ( status != OK ) { if ( GCD_global.gcd_trace_level >= 3 ) TRdisplay( "%4d GCD DMTL rejecting connection: 0x%x\n", ccb->id, status ); dmtl_shutdown( ccb, rcb, status ); } else { if ( GCD_global.gcd_trace_level >= 3 ) TRdisplay( "%4d GCD DMTL accepting connection\n", ccb->id ); /* ** Build and send TL Connection Confirmation packet. ** We use the same packet header ID as was passed in. */ gcd_init_rcb( rcb ); build_cc_parms( rcb, size, msg_parms, msg_len ); hdr.tl_id = ccb->tl.packet_id; hdr.msg_id = DAM_TL_CC; build_hdr( rcb, &hdr ); (*ccb->tl.gcc_service->send)( rcb ); } /* ** Subsequent communications must use the packet ID appropriate ** for the negotiated protocol level. ** ** Whether the connection was accepted or rejected, we assumed ** responsibility for servicing the current request, so return ** the appropriate indication. */ ccb->tl.packet_id = DAM_TL_ID_2; return( TRUE ); }