home *** CD-ROM | disk | FTP | other *** search
/ ftp.parl.clemson.edu / 2015-02-07.ftp.parl.clemson.edu.tar / ftp.parl.clemson.edu / pub / pvfs2 / orangefs-2.8.3-20110323.tar.gz / orangefs-2.8.3-20110323.tar / orangefs / src / proto / PINT-reqproto-encode.c < prev    next >
C/C++ Source or Header  |  2008-11-19  |  10KB  |  353 lines

  1. /*
  2.  * (C) 2001 Clemson University and The University of Chicago
  3.  *
  4.  * See COPYING in top-level directory.
  5.  */
  6.  
  7. #include <stdlib.h>
  8. #include <errno.h>
  9. #include <string.h>
  10.  
  11. #include "bmi.h"
  12. #include "gossip.h"
  13. #include "pvfs2-debug.h"
  14. #include "pvfs2-req-proto.h"
  15. #include "PINT-reqproto-encode.h"
  16. #include "PINT-reqproto-module.h"
  17. #include "bmi-byteswap.h"
  18. #include "pint-event.h"
  19. #include "id-generator.h"
  20. #include "pvfs2-internal.h"
  21.  
  22. #define ENCODING_TABLE_SIZE 5
  23.  
  24. /* macros for logging encode and decode events */
  25. #define ENCODE_EVENT_START(__enctype, __reqtype, __ptr) \
  26. do { \
  27.     PVFS_id_gen_t __tmp_id; \
  28.     id_gen_fast_register(&__tmp_id, (__ptr)); \
  29.     PINT_event_timestamp(__enctype, \
  30.     (int32_t)(__reqtype), 0, __tmp_id, \
  31.     PVFS_EVENT_FLAG_START); \
  32. } while(0)
  33. #define ENCODE_EVENT_STOP(__enctype, __reqtype, __ptr, __size) \
  34. do { \
  35.     PVFS_id_gen_t __tmp_id; \
  36.     id_gen_fast_register(&__tmp_id, (__ptr)); \
  37.     PINT_event_timestamp(__enctype, \
  38.     (int32_t)(__reqtype), (__size), __tmp_id, \
  39.     PVFS_EVENT_FLAG_END); \
  40. } while(0)
  41.  
  42. static PINT_encoding_table_values *PINT_encoding_table[
  43.     ENCODING_TABLE_SIZE] = {NULL};
  44.  
  45. /* PINT_encode_initialize()
  46.  *
  47.  * starts up the protocol encoding interface
  48.  *
  49.  * returns 0 on success, -PVFS_error on failure
  50.  */
  51. int PINT_encode_initialize(void)
  52. {
  53.     int ret = -PVFS_EINVAL;
  54.  
  55.     gossip_debug(GOSSIP_ENDECODE_DEBUG,"PINT_encode_initialize\n");
  56.     if (ENCODING_IS_SUPPORTED(ENCODING_LE_BFIELD))
  57.     {
  58.         /* setup little endian bytefield encoding */
  59.         PINT_encoding_table[ENCODING_LE_BFIELD] = &le_bytefield_table;
  60.         le_bytefield_table.init_fun();
  61.  
  62.         /* header prepended to all messages of this type */
  63.         *((int32_t*)&(le_bytefield_table.generic_header[0])) = 
  64.             htobmi32(PVFS2_PROTO_VERSION);
  65.         *((int32_t*)&(le_bytefield_table.generic_header[4])) = 
  66.             htobmi32(ENCODING_LE_BFIELD);
  67.  
  68.         le_bytefield_table.enc_type = ENCODING_LE_BFIELD;
  69.         ret = 0;
  70.     }
  71.     return ret;
  72. }
  73.  
  74. /* PINT_encode_finalize()
  75.  *
  76.  * shuts down the protocol encoding interface
  77.  *
  78.  * no return value
  79.  */
  80. void PINT_encode_finalize(void)
  81. {
  82.     le_bytefield_table.finalize_fun();
  83.     gossip_debug(GOSSIP_ENDECODE_DEBUG,"PINT_encode_finalize\n");
  84.     return;
  85. }
  86.  
  87.  
  88. /* PINT_encode()
  89.  * 
  90.  * encodes a buffer (containing a PVFS2 request or response) to be
  91.  * sent over the network
  92.  * 
  93.  * returns 0 on success, -PVFS_error on failure
  94.  */
  95. int PINT_encode(void* input_buffer,
  96.         enum PINT_encode_msg_type input_type,
  97.         struct PINT_encoded_msg* target_msg,
  98.         PVFS_BMI_addr_t target_addr,
  99.         enum PVFS_encoding_type enc_type)
  100. {
  101.     int ret = -PVFS_EINVAL;
  102.     target_msg->dest = target_addr;
  103.     target_msg->enc_type = enc_type;
  104.  
  105.     gossip_debug(GOSSIP_ENDECODE_DEBUG,"PINT_encode\n");
  106.     switch(enc_type)
  107.     {
  108.     case ENCODING_LE_BFIELD:
  109.         if (input_type == PINT_ENCODE_REQ)
  110.         {
  111.         ret =  PINT_encoding_table[enc_type]->op->encode_req(
  112.                     input_buffer, target_msg);
  113.         }
  114.         else if (input_type == PINT_ENCODE_RESP)
  115.         {
  116.         ret =  PINT_encoding_table[enc_type]->op->encode_resp(
  117.                     input_buffer, target_msg);
  118.         }
  119.         break;
  120.     default:
  121.         gossip_lerr("Error: encoding type not supported.\n");
  122.         ret = -PVFS_EINVAL;
  123.         break;
  124.     }
  125.     return(ret);
  126. }
  127.  
  128. /* PINT_decode()
  129.  *
  130.  * decodes a buffer (containing a PVFS2 request or response) that
  131.  * has been received from the network
  132.  *
  133.  * Parameters:
  134.  * input_buffer - encoded input
  135.  * input_type   - PINT_DECODE_REQ or PINT_DECODE_RESP
  136.  * target_msg   - pointer to struct PINT_decoded_msg, hold pointer to
  137.  *                allocated memory holding decoded message, etc.
  138.  * size         - size of encoded input
  139.  *
  140.  * Notes:
  141.  * - One must call PINT_decode_release(target_msg, input_type, 0)
  142.  *   in order for the memory allocated during the decode process to be
  143.  *   freed.
  144.  *
  145.  * returns 0 on success, -PVFS_error on failure
  146.  */
  147. int PINT_decode(void* input_buffer,
  148.         enum PINT_encode_msg_type input_type,
  149.         struct PINT_decoded_msg* target_msg,
  150.         PVFS_BMI_addr_t target_addr,
  151.         PVFS_size size)
  152. {
  153.     int i=0;
  154.     char* buffer_index = (char*)input_buffer + PINT_ENC_GENERIC_HEADER_SIZE;
  155.     int size_index = (int)size - PINT_ENC_GENERIC_HEADER_SIZE;
  156.     char* enc_type_ptr = (char*)input_buffer + 4;
  157.     int ret;
  158.     int32_t enc_type_recved, proto_ver_recved;
  159.     int proto_major_recved, proto_minor_recved;
  160.  
  161.     gossip_debug(GOSSIP_ENDECODE_DEBUG,"PINT_decode\n");
  162.     target_msg->enc_type = -1;  /* invalid */
  163.  
  164.     /* sanity check size */
  165.     if(size < PINT_ENC_GENERIC_HEADER_SIZE)
  166.     {
  167.         gossip_err("Error: poorly formatted protocol message received.\n");
  168.     gossip_err("   Too small: message only %lld bytes.\n",
  169.         lld(size));
  170.     return(-PVFS_EPROTO);
  171.     }
  172.     
  173.     /* pull the encoding type and protocol version out */
  174.     proto_ver_recved = (int)bmitoh32(*((int32_t*)input_buffer));
  175.     enc_type_recved = bmitoh32(*((int32_t*)enc_type_ptr));
  176.     proto_major_recved = proto_ver_recved / 1000;
  177.     proto_minor_recved = proto_ver_recved - (proto_major_recved*1000);
  178.  
  179.     /* check encoding type */
  180.     if(enc_type_recved != ENCODING_LE_BFIELD)
  181.     {
  182.         gossip_err("Error: poorly formatted protocol message received.\n");
  183.     gossip_err("   Encoding type mismatch: received type %d when "
  184.         "expecting %d.\n", (int)enc_type_recved, 
  185.         ENCODING_LE_BFIELD);
  186.         return(-PVFS_EPROTONOSUPPORT);
  187.     }
  188.  
  189.     /* check various protocol version possibilities */
  190.     if(proto_major_recved != PVFS2_PROTO_MAJOR)
  191.     {
  192.         gossip_err("Error: poorly formatted protocol message received.\n");
  193.     gossip_err("   Protocol version mismatch: received major version %d when "
  194.         "expecting %d.\n", (int)proto_major_recved,
  195.         PVFS2_PROTO_MAJOR);
  196.     gossip_err("   Please verify your PVFS2 installation\n");
  197.         gossip_err("   and make sure that the version is consistent.\n");
  198.         return(-PVFS_EPROTONOSUPPORT);
  199.     }
  200.  
  201.     if((input_type == PINT_DECODE_REQ) && 
  202.         (proto_minor_recved > PVFS2_PROTO_MINOR))
  203.     {
  204.         gossip_err("Error: poorly formatted protocol message received.\n");
  205.     gossip_err("   Protocol version mismatch: request has minor version %d when "
  206.         "expecting %d or lower.\n", (int)proto_minor_recved,
  207.         PVFS2_PROTO_MINOR);
  208.         gossip_err("   Client is too new for server.\n");
  209.     gossip_err("   Please verify your PVFS2 installation\n");
  210.         gossip_err("   and make sure that the version is consistent.\n");
  211.         return(-PVFS_EPROTONOSUPPORT);
  212.     }
  213.  
  214.     if((input_type == PINT_DECODE_RESP) && 
  215.         (proto_minor_recved < PVFS2_PROTO_MINOR))
  216.     {
  217.         gossip_err("Error: poorly formatted protocol message received.\n");
  218.     gossip_err("   Protocol version mismatch: request has minor version %d when "
  219.         "expecting %d or higher.\n", (int)proto_minor_recved,
  220.         PVFS2_PROTO_MINOR);
  221.         gossip_err("   Server is too old for client.\n");
  222.     gossip_err("   Please verify your PVFS2 installation\n");
  223.         gossip_err("   and make sure that the version is consistent.\n");
  224.         return(-PVFS_EPROTONOSUPPORT);
  225.     }
  226.  
  227.     for(i=0; i<ENCODING_TABLE_SIZE; i++)
  228.     {
  229.     if(PINT_encoding_table[i] && (PINT_encoding_table[i]->enc_type
  230.             == enc_type_recved))
  231.            {
  232.         struct PVFS_server_req* tmp_req;
  233.         struct PVFS_server_req* tmp_resp;
  234.         target_msg->enc_type = enc_type_recved;
  235.         if(input_type == PINT_DECODE_REQ)
  236.         {
  237.         ret = PINT_encoding_table[i]->op->decode_req(buffer_index,
  238.             size_index,
  239.             target_msg,
  240.             target_addr);
  241.         tmp_req = target_msg->buffer;
  242.         return(ret);
  243.         }
  244.         else if(input_type == PINT_DECODE_RESP)
  245.         {
  246.         ret = PINT_encoding_table[i]->op->decode_resp(buffer_index,
  247.             size_index,
  248.             target_msg,
  249.             target_addr);
  250.         tmp_resp = target_msg->buffer;
  251.         return(ret);
  252.         }
  253.         else
  254.         {
  255.         return(-PVFS_EINVAL);
  256.         }
  257.     }
  258.     }
  259.  
  260.     gossip_err("Error: poorly formatted protocol message received.\n");
  261.  
  262.     return(-PVFS_EPROTONOSUPPORT);
  263. }
  264.     
  265. /* PINT_encode_release()
  266.  *
  267.  * frees all resources associated with a message that has been
  268.  * encoded 
  269.  *
  270.  * no return value
  271.  */
  272. void PINT_encode_release(struct PINT_encoded_msg* input_buffer,
  273.              enum PINT_encode_msg_type input_type)
  274.     gossip_debug(GOSSIP_ENDECODE_DEBUG,"PINT_encode_release\n");
  275.     if (ENCODING_IS_SUPPORTED(input_buffer->enc_type))
  276.     {
  277.         PINT_encoding_table[input_buffer->enc_type]->op->encode_release(
  278.             input_buffer, input_type);
  279.     }
  280.     else
  281.     {
  282.         gossip_err("PINT_encode_release: Encoder type %d is not "
  283.                    "supported.\n", input_buffer->enc_type);
  284.     }
  285. }
  286.  
  287. /* PINT_decode_release()
  288.  *
  289.  * frees all resources associated with a message that has been
  290.  * decoded
  291.  *
  292.  * no return value
  293.  */
  294. void PINT_decode_release(struct PINT_decoded_msg* input_buffer,
  295.              enum PINT_encode_msg_type input_type)
  296. {
  297.     gossip_debug(GOSSIP_ENDECODE_DEBUG,"PINT_decode_release\n");
  298.     if (ENCODING_IS_SUPPORTED(input_buffer->enc_type))
  299.     {
  300.         PINT_encoding_table[input_buffer->enc_type]->op->decode_release(
  301.             input_buffer, input_type);
  302.     }
  303.     else if (input_buffer->enc_type == -1)
  304.     {
  305.         /* invalid return from PINT_decode, quietly return */
  306.         ;
  307.     }
  308.     else
  309.     {
  310.         gossip_err("PINT_decode_release: Encoder type %d is not "
  311.                    "supported.\n", input_buffer->enc_type);
  312.     }
  313. }
  314.  
  315.  
  316. /* PINT_encode_calc_max_size()
  317.  *
  318.  * calculates maximum size of the encoded version of a protocol message.
  319.  *
  320.  * returns max size of encoded buffer on success, -PVFS_error on failure
  321.  */
  322. int PINT_encode_calc_max_size(
  323.     enum PINT_encode_msg_type input_type,
  324.     enum PVFS_server_op op_type,
  325.     enum PVFS_encoding_type enc_type)
  326. {    
  327.     int ret = -PVFS_EINVAL;
  328.  
  329.     gossip_debug(GOSSIP_ENDECODE_DEBUG,"PINT_encode_calc_max_size\n");
  330.     switch(enc_type)
  331.     {
  332.     case ENCODING_LE_BFIELD:
  333.         ret = PINT_encoding_table[enc_type]->op->encode_calc_max_size
  334.         (input_type, op_type);
  335.         break;
  336.     default:
  337.         gossip_lerr("Error: encoding type not supported.\n");
  338.         break;
  339.     }
  340.  
  341.     return(ret);
  342. }
  343.  
  344. /*
  345.  * Local variables:
  346.  *  c-indent-level: 4
  347.  *  c-basic-offset: 4
  348.  * End:
  349.  *
  350.  * vim: ts=8 sts=4 sw=4 expandtab
  351.  */
  352.