Simple C Client Template for LDRdataFindServer

The LDRdataFindServer listens on a Globus GSI protected socket and so requires GSI authentication in order to invoke data finding operations. The server and the standard client LSCdataFind are both written in Python but one can write a client using any language that has GSI binding/libraries. In addtion to Python one can easily find libraries for C, Tcl, and Java.

Here we present a short tutorial on how to write a C client for LDRdataFindServer. We don't code up a fully functional client and just show how to bootstrap a client that can 'ping' the server.

  1. Install Globus: You will need access to a Globus installation so that you can link your C code against the Globus GSI and other libraries. Here is one way to get yourself set up with an installation (there are other ways that may be more or less efficient for your particular needs):
    • Dowload the correct Globus 4.0.x binary tarball for your platform from http://www.globus.org/toolkit/downloads/.
    • As yourself (you don't need to be a special user) decide where you will install Globus and defined GLOBUS_LOCATION to point to that location:
      export GLOBUS_LOCATION=/home/skoranda/globus-4.0.5-from-binary
      
    • Untar the tarball and change into the created directory:
      tar -zxvf gt4.0.5-x86_fc_4-installer.tar.gz
      cd gt4.0.5-x86_fc_4-installer
      
    • Configure, make, and make install (do not worry about JAVA and ANT warnings since you are coding in C):
      ./configure --prefix=$GLOBUS_LOCATION
      make
      make install
      
    • Set up your environment:
      source $GLOBUS_LOCATION/etc/globus-user-env.sh
      
    • Create some necessary pieces not normally in a binary installation (use gcc64dbg if working on a 64 bit OS):
      gpt-build -nosrc gcc32dbg
      gpt-postinstall
      
  2. Setup your Sandbox: You need to setup your environment and create a file to be included in your Makefile:
    globus-makefile-header --flavor=gcc32dbg globus_xio > myMakefile.include
    
  3. Code up the client: You can download the simple client template but we also include it here for reference with more verbose comments:
    #include <stdlib.h>
    #include <stdio.h>
    
    #include "globus_xio.h"
    #include "globus_xio_gsi.h"
    
    int
    main(
        int                             argc,
        char *                          argv[])
    {
        globus_xio_driver_t             tcp_driver;
        globus_xio_driver_t             gsi_driver;
        globus_xio_stack_t              stack;
        globus_xio_handle_t             handle;
        globus_xio_attr_t               attr;
        globus_size_t                   nbytes;
        char *                          contact_string = NULL;
        char                            incoming[256];
    
        /* grab the host:port combination from command line */
        contact_string = argv[1];
    
        /* Activate the XIO module. All Globus C libraries 
           are usually initialized by activating a module. */
          
        globus_module_activate(GLOBUS_XIO_MODULE);
    
        /* Load the TCP and GSI drivers. We use the TCP driver 
           because the server listens on a TCP (as opposed to UDP say)
           socket and we need the GSI driver because the server expects
           GSI authentication.
           
           XIO is structured to use drivers that can be layered on top 
           of one another so we load both now and layer them below. */
        globus_xio_driver_load("tcp", &tcp_driver);
        globus_xio_driver_load("gsi", &gsi_driver);
        
        /* Create a driver stack and load it first with the
           TCP driver and then the GSI driver. TCP is first so
           that it is at the bottom of the stack and the outgoing payload
           is sent through it last, after the GSI driver has done its work
           
           The incoming payload is treated in reverse. The TCP driver
           manages it coming in from the wire and then the GSI driver
           handles anything it needs to handle before passing it off to
           the application/user level. */
        globus_xio_stack_init(&stack, NULL);
        globus_xio_stack_push_driver(stack, tcp_driver);
        globus_xio_stack_push_driver(stack, gsi_driver);
    
        /* create a handle */
        globus_xio_handle_create(&handle, stack);
    
        /* we need an attribute to decorate the handle */
        globus_xio_attr_init(&attr);
    
        /* Because the pyGlobus LDRdataFindServer uses a clear channel and
           by default the XIO GSI driver does not, we need to set it directly 
           on the XIO GSI driver and then decorate the handle. 
           
           We set the protection level to none, which does not mean no
           authentication but instead means that no encryption or integrity
           checking is done on the payload. */
        globus_xio_attr_cntl(
            attr, 
            gsi_driver, 
            GLOBUS_XIO_GSI_SET_PROTECTION_LEVEL,
            GLOBUS_XIO_GSI_PROTECTION_LEVEL_NONE
            ); 
    
        /* connect to the server using the decorated handle */
        globus_xio_open(handle, contact_string, attr);
    
        /* send 5 bytes 'P I N G \0' to ping the server */
        globus_xio_write(handle, "PING\0", 5 , 5, &nbytes, NULL);
    
        /* read the incoming message from the server */
        globus_xio_read(
            handle, 
            incoming, 
            sizeof(incoming) - 1, 
            sizeof(incoming) - 1, 
            &nbytes, 
            NULL);
    
        /* first byte is return value followed by null byte and then the
           message back from the server */
        if(nbytes > 0){
                fprintf(stdout, "Return value from server: %s\n", incoming);
                fprintf(stdout, "Message from server: %s\n", incoming + 2);
        }
        
        /* clean up */
        globus_xio_close(handle, NULL);
        globus_module_deactivate_all();
    
        return 0;
    }
    
    
  4. Create a Makefile: Any Makefile will do, just be sure to include the file you generated earlier. Here is one possibility:
    include ./myMakefile.include
    
    all: pingclient
    
    pingclient: pingclient.o
        $(GLOBUS_CC) -o pingclient pingclient.o 
            $(GLOBUS_LDFLAGS) $(GLOBUS_LIBS) $(GLOBUS_PKG_LIBS)
    
    pingclient.o: pingclient.c
        $(GLOBUS_CC) $(GLOBUS_CFLAGS) $(GLOBUS_INCLUDES)
            -g -c -o pingclient.o pingclient.c
    
    clean:
        -rm -f *.o pingclient
    
  5. Build the client:
    [skoranda@localhost clientwork]$ make
    /usr/bin/gcc -g -Wall 
          -I/home/skoranda/globus-4.0.4-from-binary-xio/include/gcc32dbg 
          -g -c -o pingclient.o pingclient.c
    /usr/bin/gcc -o pingclient pingclient.o 
                    -L/home/skoranda/globus-4.0.4-from-binary-xio/lib
                    -L/home/skoranda/globus-4.0.4-from-binary-xio/lib
                    -lglobus_xio_gcc32dbg -lgssapi_error_gcc32dbg
                    -lglobus_gss_assist_gcc32dbg
                    -lglobus_gssapi_gsi_gcc32dbg
                    -lglobus_gsi_proxy_core_gcc32dbg
                    -lglobus_gsi_credential_gcc32dbg
                    -lglobus_gsi_callback_gcc32dbg -lglobus_oldgaa_gcc32dbg
                    -lglobus_gsi_sysconfig_gcc32dbg
                    -lglobus_gsi_cert_utils_gcc32dbg
                    -lglobus_openssl_gcc32dbg
                    -lglobus_openssl_error_gcc32dbg
                    -lglobus_callout_gcc32dbg -lglobus_proxy_ssl_gcc32dbg
                    -lglobus_common_gcc32dbg -lssl_gcc32dbg
                    -lcrypto_gcc32dbg -lltdl_gcc32dbg -lm -ldl -ldl
    
  6. Set up security: You need to aim your client at an LDRdataFindServer for which you are already authorized to use (your cert subject or DN is in the grid-mapfile). On the client end you need to make sure your Globus installation has access to the DOEGrids CA files and that you have a valid proxy certificate.

    Here is one possible way to set things up quickly:

    • If you have a copy of the LDG client installed then in another shell source its setup file as you normally would and then determine what it set X509_CERT_DIR to:
      [skoranda@localhost ~]$ source ldg-4.4/setup.sh
      [skoranda@localhost ~]$ echo $X509_CERT_DIR
      /home/skoranda/ldg-4.4/vdt/globus/TRUSTED_CA
      
    • In your coding environment define X509_CERT_DIR to point to the same location.
    • Run grid-proxy-init as you normally would.
  7. Run the client: You should see the welcome message from the server you aimed at:
    [skoranda@localhost clientwork]$ ./pingclient "nemo-dataserver.phys.uwm.edu:30010"
    Return value from server: 0
    Message from server: LDRdataFindServer at nemo-dataserver.phys.uwm.edu is alive
    

LDR Logo
Any opinions, findings, and conclusions or recommendations expressed in this material are those of the author(s) and do not necessarily reflect the views of the National Science Foundation.