home *** CD-ROM | disk | FTP | other *** search
/ Australian Personal Computer 1999 May / APC452.ISO / netkit / xitami / xitami.exe / LRWPLIB.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-01-26  |  9.9 KB  |  303 lines

  1. /************************************************************************
  2.                Copyright (c) 1997 by Total Control Software
  3.                          All Rights Reserved
  4. ------------------------------------------------------------------------
  5.  
  6. Module Name:    lrwplib.c
  7.  
  8. Description:    Small library of routines to assist with the creation
  9.                 of LRWP Peer applications.
  10.  
  11. Creation Date:  1/5/98 9:47:27PM
  12.  
  13. # License:      This is free software.  You may use this software for any
  14. #               purpose including modification/redistribution, so long as
  15. #               this header remains intact and that you do not claim any
  16. #               rights of ownership or authorship of this software.  This
  17. #               software has been tested, but no warranty is expressed or
  18. #               implied.
  19.  
  20. ************************************************************************/
  21.  
  22. #include "lrwplib.h"
  23.  
  24. #define SIZELEN     9
  25. #define ALLOC_INCR  1024
  26.  
  27.  
  28. static int
  29. read_full_TCP(
  30.     sock_t handle,                      /*  Socket handle                    */
  31.     void *buffer,                       /*  Buffer to receive data           */
  32.     size_t length                       /*  Full amount of data to read      */
  33.     );
  34.  
  35. /*  ---------------------------------------------------------------------[<]-
  36.     Function: lrwp_connect
  37.  
  38.     Connects to the LRWP agent running in Xitami on host and port.  Sends
  39.     the given appname to use as the URI alias that will trigger requests to
  40.     be sent to this peer.  If vhost is given, this peer will only be sent
  41.     requests origininating from that virtual host.  This function assumes
  42.     that the LRWP structure is uninitialized and clears it before use.
  43.  
  44.     Returns NULL on success and a pointer to an error message otherwise.
  45.     ---------------------------------------------------------------------[>]-*/
  46.  
  47. char* lrwp_connect(LRWP* lrwp,          /* pointer to UNCONNECTED LRWP object */
  48.                    char* appname,       /* Name or alias of Peer app         */
  49.                    char* host,          /* hostname/IP address to connect to */
  50.                    char* port,          /* string containing port number     */
  51.                    char* vhost)         /* optional virtual hostname         */
  52. {
  53.     static char buf[1024];
  54.     int         len;
  55.  
  56.     /* Initialize LRWP structure.  Assumes this is first use. */
  57.     lrwp->sock      = 0;
  58.     lrwp->cgi       = NULL;
  59.     lrwp->post_data = NULL;
  60.     lrwp->outbuf    = NULL;
  61.     lrwp->size      = 0;
  62.     lrwp->allocated = 0;
  63.  
  64.  
  65.     /* Attempt the connection */
  66.     ip_nonblock = FALSE;                /*  Use blocking socket i/o          */
  67.     lrwp->sock = connect_TCP(host, port);
  68.     if (lrwp->sock == INVALID_SOCKET) {
  69.         sprintf(buf, "ERROR: Unable to connect (%s)", sockmsg());
  70.         return buf;
  71.     }
  72.  
  73.     /* send the startup sting */
  74.     sprintf(buf, "%s\xFF%s\xFF%s", appname, vhost?vhost:"", "");
  75.     if (write_TCP(lrwp->sock, buf, strlen(buf)) == SOCKET_ERROR) {
  76.         sprintf(buf, "ERROR: Unable to send startup string (%s)", sockmsg());
  77.         return buf;
  78.     }
  79.  
  80.     /* wait for an acknowledgement... */
  81.     len = read_TCP(lrwp->sock, buf, sizeof(buf)-1);
  82.     if (len == SOCKET_ERROR) {
  83.         sprintf(buf, "ERROR: Unable to receive acknowledgement string (%s)", sockmsg());
  84.         return buf;
  85.     }
  86.     buf[len] = 0;
  87.  
  88.     if (streq(buf, "OK"))
  89.         return NULL;
  90.     else
  91.         return buf;
  92. }
  93.  
  94. /*  ---------------------------------------------------------------------[<]-
  95.     Function: lrwp_accept_request
  96.  
  97.     This funation waits for and recieves a request from the LRWP agent, and
  98.     populates the LRWP structure with the request data.
  99.  
  100.     Returns 0 on success and -1 otherwise.
  101.     ---------------------------------------------------------------------[>]-*/
  102.  
  103. int  lrwp_accept_request(LRWP* lrwp)    /* pointer to CONNECTED LRWP object  */
  104. {
  105.     char    sizebuf[SIZELEN+1];
  106.     int     len;
  107.     int     size;
  108.     DESCR   descr;
  109.     char*   temp;
  110.  
  111.     /* read the size of the CGI environment */
  112.     len = read_full_TCP(lrwp->sock, sizebuf, SIZELEN);
  113.     if (len == SOCKET_ERROR || len != SIZELEN)
  114.         return -1;
  115.     sizebuf[len] = 0;
  116.     size = atoi(sizebuf);
  117.  
  118.     /*  read the CGI environment data */
  119.     temp = mem_alloc(size+1);           /* **** Should be checking this!!! */
  120.     len = read_full_TCP(lrwp->sock, temp, size);
  121.     if (len == SOCKET_ERROR || len != size) {
  122.         mem_free(temp);
  123.         return -1;
  124.     }
  125.  
  126.     /*  and convert it to a Symbol Table */
  127.     descr.size = size;
  128.     descr.data = temp;
  129.     lrwp->cgi = descr2symb(&descr);
  130.     mem_free(temp);
  131.  
  132.     /*  now read the size of the post data */
  133.     len = read_full_TCP(lrwp->sock, sizebuf, SIZELEN);
  134.     if (len == SOCKET_ERROR || len != SIZELEN) {
  135.         sym_delete_table(lrwp->cgi);
  136.         lrwp->cgi = NULL;
  137.         return -1;
  138.     }
  139.     sizebuf[len] = 0;
  140.     size = atoi(sizebuf);
  141.  
  142.     /*  and finally, read the post data, if any */
  143.     if (size) {
  144.         lrwp->post_data = mem_alloc(size+1); /* **** Should be checking this!!! */
  145.         len = read_full_TCP(lrwp->sock, lrwp->post_data, size);
  146.         if (len == SOCKET_ERROR || len != size) {
  147.             sym_delete_table(lrwp->cgi);
  148.             lrwp->cgi = NULL;
  149.             mem_free(lrwp->post_data);
  150.             lrwp->post_data = NULL;
  151.             return -1;
  152.         }
  153.     }
  154.     else
  155.         lrwp->post_data = mem_strdup("");
  156.  
  157.     return 0;
  158. }
  159.  
  160. /*  ---------------------------------------------------------------------[<]-
  161.     Function: lrwp_send_string
  162.  
  163.     This function appends a string to the response buffer.
  164.     lrwp_finish_request() must be called to send the response back to Xitami.
  165.  
  166.     Returns 0 on success and -1 otherwise.
  167.     ---------------------------------------------------------------------[>]-*/
  168.  
  169. int  lrwp_send_string(LRWP* lrwp,       /* pointer to CONNECTED LRWP object  */
  170.                       char* st)         /* an ouput string                   */
  171. {
  172.     return lrwp_send_data(lrwp, st, strlen(st));
  173. }
  174.  
  175. /*  ---------------------------------------------------------------------[<]-
  176.     Function: lrwp_send_data
  177.  
  178.     Appends a buffer of (possibly binary) data of the specified size to
  179.     the response buffer.  lrwp_finish_request() must be called to send the
  180.     response back to Xitami.
  181.  
  182.     Returns 0 on success and -1 otherwise.
  183.     ---------------------------------------------------------------------[>]-*/
  184.  
  185. int  lrwp_send_data(LRWP* lrwp,         /* pointer to CONNECTED LRWP object  */
  186.                     void* data,         /* pointer to a data buffer          */
  187.                     size_t len)         /* size of the data buffer           */
  188. {
  189.     char*   newPtr;
  190.     size_t  newAlloc;
  191.  
  192.     /* reallocate if necessary */
  193.     if ((lrwp->size + len) > lrwp->allocated) {
  194.         newAlloc = max(lrwp->allocated + len, lrwp->allocated + ALLOC_INCR);
  195.         if (! lrwp->outbuf)
  196.             newPtr = mem_alloc(newAlloc);
  197.         else
  198.             newPtr = mem_realloc(lrwp->outbuf, newAlloc);
  199.         if (!newPtr)
  200.             return -1;
  201.         lrwp->outbuf = newPtr;
  202.         lrwp->allocated = newAlloc;
  203.     }
  204.     memcpy(lrwp->outbuf + lrwp->size, data, len);
  205.     lrwp->size += len;
  206.     return 0;
  207. }
  208.  
  209. /*  ---------------------------------------------------------------------[<]-
  210.     Function: lrwp_finish_request
  211.  
  212.     Completes the request by sending the response buffer back to Xitami
  213.     and prepares the lwrp structure to receive another request.
  214.  
  215.     Returns 0 on success and -1 otherwise.
  216.     ---------------------------------------------------------------------[>]-*/
  217.  
  218. int  lrwp_finish_request(LRWP* lrwp)    /* pointer to CONNECTED LRWP object  */
  219. {
  220.     char    sizebuf[SIZELEN+1];
  221.  
  222.     sprintf(sizebuf, "%09ld", lrwp->size);
  223.     if (write_TCP(lrwp->sock, sizebuf, SIZELEN) == SOCKET_ERROR) {
  224.         lrwp_cleanup(lrwp);
  225.         return -1;
  226.     }
  227.  
  228.     if (write_TCP(lrwp->sock, lrwp->outbuf, lrwp->size) == SOCKET_ERROR) {
  229.         lrwp_cleanup(lrwp);
  230.         return -1;
  231.     }
  232.     lrwp_cleanup(lrwp);
  233.     return 0;
  234. }
  235.  
  236. /*  ---------------------------------------------------------------------[<]-
  237.     Function: lrwp_close
  238.  
  239.     Closes the connection to Xitami.
  240.  
  241.     Returns 0 on success and -1 otherwise.
  242.     ---------------------------------------------------------------------[>]-*/
  243.  
  244. int  lrwp_close(LRWP* lrwp)             /* pointer to CONNECTED LRWP object  */
  245. {
  246.     close_socket(lrwp->sock);
  247.     lrwp->sock = 0;
  248.     lrwp_cleanup(lrwp);
  249.     return 0;
  250. }
  251.  
  252. /*  ---------------------------------------------------------------------[<]-
  253.     Function: lrwp_cleanup
  254.  
  255.     Cleans up the LRWP structure.
  256.  
  257.     ---------------------------------------------------------------------[>]-*/
  258.  
  259. void lrwp_cleanup(LRWP* lrwp)
  260. {
  261.     if (lrwp->cgi)
  262.         sym_delete_table(lrwp->cgi);
  263.  
  264.     if (lrwp->post_data)
  265.         mem_free(lrwp->post_data);
  266.  
  267.     if (lrwp->outbuf)
  268.         mem_free(lrwp->outbuf);
  269.  
  270.     lrwp->cgi       = NULL;
  271.     lrwp->post_data = NULL;
  272.     lrwp->outbuf    = NULL;
  273.     lrwp->size      = 0;
  274.     lrwp->allocated = 0;
  275. }
  276.  
  277.  
  278. /*  -------------------------------------------------------------------------
  279.     Function: read_full_TCP
  280.  
  281.     Helper function to read the full number of bytes specified from the socket.
  282.  
  283.     -------------------------------------------------------------------------*/
  284. static int
  285. read_full_TCP(
  286.     sock_t handle,                      /*  Socket handle                    */
  287.     void *buffer,                       /*  Buffer to receive data           */
  288.     size_t length                       /*  Full amount of data to read      */
  289.     )
  290. {
  291.     size_t  numRead = 0;
  292.     int     chunkLen;
  293.  
  294.     while (numRead < length) {
  295.         chunkLen = read_TCP(handle, ((char*)buffer)+numRead, length-numRead);
  296.         if (chunkLen == SOCKET_ERROR)
  297.             return SOCKET_ERROR;
  298.         numRead += chunkLen;
  299.     }
  300.     return numRead;
  301. }
  302.  
  303.