|
i |
This is a debug version substitution for the normal client code. It will directly call the server code so that you can debug the protocol in a single process. AutoXDR will also produce template code for the client side main procedure (*-clmain.c) and the server side implementation procedures (*-svstub.c). They are not shown here, but they can be seen by downloading the AutoXDR tarball and generating the sources. The following example is from NFSv4 with all but one queued call removed:
/* * DO NOT EDIT THIS FILE (nfsv4-debug.c) * * It has been AutoGen-ed Saturday August 12, 2006 at 11:32:10 AM PDT * From the definitions nfsv4.def * and the template file autoxdr.tpl * * This file has been generated by the AutoXDR AutoGen template suite. * * These files are compatible with: * RFC1831 - Remote Procedure Call Protocol Specification Version 2 * RFC1832 - External Data Representation Standard * and are intended to be used as a layer on top of the ONC IDL * in conjunction with RPCGEN. * */ #include <stdio.h> #include <errno.h> #include "nfsv4-svhdr.h" #include "nfsv4-clhdr.h" static int call_server( int proc_id, caddr_t p_args, caddr_t p_res ) { void* pr = NULL; switch (proc_id) { case NFS4_NULL: pr = nfs4_null_4_svc( (void*)p_args, (struct svc_req *)NULL ); break; case NFS4_COMPOUND: pr = nfs4_compound_4_svc( (nfs4_compound_args*)p_args, (struct svc_req *)NULL ); if (pr != NULL) memcpy( (void*)p_res, (void*)pr, sizeof( nfs4_compound_res )); break; default: return RPC_PROCUNAVAIL; } return (pr == NULL) ? RPC_FAILED : RPC_SUCCESS; } /* * IF someone calls this with an invalid cookie, exit the program here */ static void sequence_fail( const char* pz_which ) { static const char z_fail_fmt[] = "NFS Calling sequence error for %s\n"; fprintf( stderr, z_fail_fmt, pz_which ); exit( 1 ); } void* nfs4_null_4( void* argp, CLIENT* clnt ) { int status; static char res; status = call_server( NFS4_NULL, (caddr_t)argp, (caddr_t)&res ); if (status != RPC_SUCCESS) return NULL; return &res; } typedef void (*tp_done)(void); typedef struct { int32_t magic; int32_t alloc_ct; int32_t used_ct; u_nfs4_compound_args* p_data; void* user_cookie; tp_done* pap_done; nfs4_compound_args args; } t_nfs4_compound_cookie; /* * magic = version << 24 + proc-num << 20 + program id */ #define NFS4_COMPOUND_MAGIC 0x401186A3 /* * Free up the operation space. */ static void free_nfs4_compound_cookie( t_nfs4_compound_cookie* pC ) { { int ct = pC->used_ct; tp_done* p_cp = pC->pap_done; u_nfs4_compound_args* p_arg = pC->p_data; while (--ct >= 0) { switch (p_arg->argop) { case NFS4_ACCESS4: { tp_nfs4_access4_done pc = (tp_nfs4_access4_done)*p_cp; ACCESS4args* pa = &(p_arg->u_nfs4_compound_args_u.op_access4); if (pc == NULL) break; (*pc)( pC->user_cookie, (nfs4_compound_res*)NULL, NFS4_STATUS_OMITTED, pa->requested, 0 ); break; } } p_arg++; p_cp++; } } if (pC->p_data != NULL) free( (void*)pC->p_data ); if (pC->pap_done != NULL) free( (void*)pC->pap_done ); pC->magic = 0; free( (void*)pC ); } /* * Out of operation space. Expand it. */ static int expand_nfs4_compound_cookie( t_nfs4_compound_cookie* pC ) { void* p; pC->alloc_ct += 4; p = realloc( (void*)pC->p_data, pC->alloc_ct * sizeof( u_nfs4_compound_args )); if (p == NULL) { free_nfs4_compound_cookie( pC ); return ENOMEM; } pC->p_data = (u_nfs4_compound_args*)p; p = realloc( (void*)pC->pap_done, pC->alloc_ct * sizeof( tp_done )); if (p == NULL) { free_nfs4_compound_cookie( pC ); return ENOMEM; } pC->pap_done = (tp_done*)p; return 0; } /* * INITIALIZE the state of the COMPOUND request */ int init_nfs4_compound( t_nfs_cookie* p_my_cookie, utf8string* tag_in /* in */, void* user_cookie ) { t_nfs4_compound_cookie* pC = (t_nfs4_compound_cookie*)malloc( sizeof( *pC )); /* * allocate our cookie, the start of the array of operation arguments * and an array of pointers to procedures that will be called when * the results are ready. */ if (pC == NULL) return ENOMEM; memset( (void*)pC, 0, sizeof( *pC )); pC->p_data = (u_nfs4_compound_args*)malloc( 4 * sizeof( u_nfs4_compound_args )); if (pC->p_data == NULL) { free( (void*)pC ); return ENOMEM; } pC->pap_done = (tp_done*)malloc( 4 * sizeof(tp_done) ); if (pC->pap_done == NULL) { free_nfs4_compound_cookie( pC ); return ENOMEM; } /* * Everything is allocated. Initiaize our private data, plus * the "extra" arguments for this combined op. */ *p_my_cookie = (t_nfs_cookie)pC; pC->magic = NFS4_COMPOUND_MAGIC; pC->alloc_ct = 4; pC->used_ct = 0; pC->user_cookie = user_cookie; pC->args.tag_in = *tag_in; pC->args.minorversion = 0; return 0; } /* * SEND the COMPOUND request * * This routine finally sends the command buffer and invokes * all the callback routines. */ int send_nfs4_compound( t_nfs_cookie my_cookie, CLIENT* clnt ) { t_nfs4_compound_cookie* pC = (t_nfs4_compound_cookie*)my_cookie; nfs4_compound_res* p_res; if (pC->magic != NFS4_COMPOUND_MAGIC) sequence_fail( "send_nfs4_compound" ); pC->args.argarray.argarray_val = pC->p_data; pC->args.argarray.argarray_len = pC->used_ct * sizeof( *(pC->p_data) ); /* * Send the request. The result is a pointer to a result struct. * Unless the send fails. In that case, we get NULL back. */ { static nfs4_compound_res res; memset( (void*)&res, 0, sizeof( res )); if ( call_server( NFS4_COMPOUND, (caddr_t)&(pC->args), (caddr_t)&res ) != RPC_SUCCESS ) p_res = NULL; else p_res = &res; } if (p_res == NULL) { free_nfs4_compound_cookie( pC ); return (errno>0) ? 0-errno : -1; } { u_nfs4_compound_res* pa_res = p_res->resarray.resarray_val; u_nfs4_compound_args* pa_arg = pC->p_data; tp_done* p_cp = pC->pap_done; int res_ct = p_res->resarray.resarray_len / sizeof( *pa_res ); int req_ct = pC->used_ct; int res = p_res->status; /* * FOR each result AND for as long as we get OK (zero) back, * DO call the result callback procedure */ while (--req_ct >= 0) { res_ct--; switch (pa_arg->argop) { case NFS4_ACCESS4: { tp_nfs4_access4_done pc = (tp_nfs4_access4_done)*p_cp; ACCESS4args* pa = &(pa_arg->u_nfs4_compound_args_u.op_access4); ACCESS4res* pr = &(pa_res->u_nfs4_compound_res_u.op_access4); if (pc == NULL) break; if (res_ct >= 0) (*pc)( pC->user_cookie, p_res, p_res->status, pa->requested, pr ); else (*pc)( pC->user_cookie, NULL, p_res->status, pa->requested, 0 ); break; } } pa_arg++; p_cp++; pa_res++; } pC->used_ct = 0; /* prevent the calling of the callback procedures */ free_nfs4_compound_cookie( pC ); return res; } } /* * Stash the data for each flavor of operation. The "int" value * returned is either ENOMEM or 0 (EOK). */ int do_nfs4_access4( t_nfs_cookie my_cookie, tp_nfs4_access4_done p_done, uint32_t requested /* in */ ) { t_nfs4_compound_cookie* pC = (t_nfs4_compound_cookie*)my_cookie; int idx; ACCESS4args* p_args; if (pC->magic != NFS4_COMPOUND_MAGIC) sequence_fail( "do_nfs4_access4" ); idx = pC->used_ct; if (++(pC->used_ct) >= pC->alloc_ct) if (expand_nfs4_compound_cookie( pC ) != 0) return ENOMEM; pC->pap_done[ idx ] = (tp_done)p_done; pC->p_data[ idx ].argop = NFS4_ACCESS4; memset( (void*)&(pC->p_data[ idx ].u_nfs4_compound_args_u), 0, sizeof( pC->p_data[ idx ].u_nfs4_compound_args_u )); p_args = &(pC->p_data[ idx ].u_nfs4_compound_args_u.op_access4); p_args->requested = requested; return 0; } |