"Fossies" - the Fresh Open Source Software Archive

Member "httperf-0.9.0/src/gen/sess_cookie.c" (7 Apr 2007, 6247 Bytes) of package /linux/www/old/httperf-0.9.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "sess_cookie.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2     httperf -- a tool for measuring web server performance
    3     Copyright 2000-2007 Hewlett-Packard Company and Contributors listed in
    4     AUTHORS file. Originally contributed by David Mosberger-Tang
    5 
    6     This file is part of httperf, a web server performance measurment
    7     tool.
    8 
    9     This program is free software; you can redistribute it and/or
   10     modify it under the terms of the GNU General Public License as
   11     published by the Free Software Foundation; either version 2 of the
   12     License, or (at your option) any later version.
   13     
   14     In addition, as a special exception, the copyright holders give
   15     permission to link the code of this work with the OpenSSL project's
   16     "OpenSSL" library (or with modified versions of it that use the same
   17     license as the "OpenSSL" library), and distribute linked combinations
   18     including the two.  You must obey the GNU General Public License in
   19     all respects for all of the code used other than "OpenSSL".  If you
   20     modify this file, you may extend this exception to your version of the
   21     file, but you are not obligated to do so.  If you do not wish to do
   22     so, delete this exception statement from your version.
   23 
   24     This program is distributed in the hope that it will be useful,
   25     but WITHOUT ANY WARRANTY; without even the implied warranty of
   26     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   27     General Public License for more details.
   28 
   29     You should have received a copy of the GNU General Public License
   30     along with this program; if not, write to the Free Software
   31     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  
   32     02110-1301, USA
   33 */
   34 
   35 /* This module intercepts `Set-Cookie:' headers on a per-session basis
   36    and includes set cookies in future calls of the session.
   37 
   38    Missing features:
   39     - intercepted cookies are always sent, independent of any constraints
   40        that may be present in the set-cookie header
   41 */
   42 
   43 #include <assert.h>
   44 #include <ctype.h>
   45 #include <errno.h>
   46 #include <stdio.h>
   47 #include <stdlib.h>
   48 #include <string.h>
   49 
   50 #include <httperf.h>
   51 #include <call.h>
   52 #include <conn.h>
   53 #include <core.h>
   54 #include <event.h>
   55 #include <session.h>
   56 
   57 #define MAX_COOKIE_LEN  256
   58 
   59 #define SESS_PRIVATE_DATA(c) \
   60   ((Sess_Private_Data *) ((char *)(c) + sess_private_data_offset))
   61 
   62 #define CALL_PRIVATE_DATA(c) \
   63   ((Call_Private_Data *) ((char *)(c) + call_private_data_offset))
   64 
   65 typedef struct Sess_Private_Data
   66   {
   67     /* For now, we support just one cookie per session.  If we get
   68        more than one cookie, we'll print a warning message when
   69        --debug is turned on.  */
   70     size_t cookie_len;
   71     /* We can't malloc the cookie string because we may get a
   72        ``Set-Cookie:'' while there are calls pending that refer to an
   73        existing cookie.  So if we were to malloc & free cookies, we
   74        would have to use reference counting to avoid the risk of
   75        dangling pointers.  */
   76     char cookie[MAX_COOKIE_LEN];
   77   }
   78 Sess_Private_Data;
   79 
   80 /* We need the call private data to ensure that the cookie gets set
   81    only once.  EV_CALL_ISSUE gets signalled each time a call is sent
   82    on a connection.  Since a connection may fail, the same call may be
   83    issued multiple times, hence we need to make sure that the cookie
   84    gets set only once per call.  */
   85 typedef struct Call_Private_Data
   86   {
   87     u_int cookie_present;   /* non-zero if cookie has been set already */
   88     char cookie[MAX_COOKIE_LEN];
   89   }
   90 Call_Private_Data;
   91 
   92 static size_t sess_private_data_offset = -1;
   93 static size_t call_private_data_offset = -1;
   94 
   95 /* A simple module that collects cookies from the server responses and
   96    includes them in future calls to the server.  */
   97 
   98 static void
   99 call_issue (Event_Type et, Object *obj, Any_Type regarg, Any_Type callarg)
  100 {
  101   Call_Private_Data *cpriv;
  102   Sess_Private_Data *priv;
  103   Sess *sess;
  104   Call *call;
  105 
  106   assert (et == EV_CALL_ISSUE && object_is_call (obj));
  107   call = (Call *) obj;
  108   cpriv = CALL_PRIVATE_DATA (call);
  109 
  110   if (cpriv->cookie_present)
  111     /* don't do anything if cookie has been set already */
  112     return;
  113 
  114   sess = session_get_sess_from_call (call);
  115   priv = SESS_PRIVATE_DATA (sess);
  116 
  117   if (priv->cookie_len > 0)
  118     {
  119       if (DBG > 1)
  120     fprintf (stderr, "call_issue.%ld: inserting `%s'\n",
  121          call->id, priv->cookie);
  122       cpriv->cookie_present = 1;
  123       memcpy (cpriv->cookie, priv->cookie, priv->cookie_len + 1);
  124       call_append_request_header (call, cpriv->cookie, priv->cookie_len);
  125     }
  126 }
  127 
  128 static void
  129 call_recv_hdr (Event_Type et, Object *obj, Any_Type regarg, Any_Type callarg)
  130 {
  131   char *hdr, *start, *end;
  132   Sess_Private_Data *priv;
  133   size_t len;
  134   struct iovec *line;
  135   Sess *sess;
  136   Call *call;
  137 
  138   assert (et == EV_CALL_RECV_HDR && object_is_call (obj));
  139   call = (Call *) obj;
  140   sess = session_get_sess_from_call (call);
  141   priv = SESS_PRIVATE_DATA (sess);
  142 
  143   line = callarg.vp;
  144   hdr = line->iov_base;
  145   if (tolower (hdr[0]) == 's' && line->iov_len > 12
  146       && strncasecmp (hdr + 1, "et-cookie: ", 11) == 0)
  147     {
  148       /* munch time! */
  149       start = hdr + 12;
  150       end = strchr (start, ';');
  151       if (!end)
  152     end = hdr + line->iov_len;
  153       len = end - start;
  154       if (DBG > 0 && priv->cookie_len > 0)
  155     fprintf (stderr, "%s: can't handle more than one "
  156          "cookie at a time, replacing existing one\n", prog_name);
  157       if (len + 10 >= MAX_COOKIE_LEN)
  158     {
  159       fprintf (stderr, "%s.sess_cookie: truncating cookie to %d bytes\n",
  160            prog_name, MAX_COOKIE_LEN - 11);
  161       len = MAX_COOKIE_LEN - 11;
  162     }
  163       memcpy (priv->cookie, "Cookie: ", 8);
  164       memcpy (priv->cookie + 8, start, len);
  165       memcpy (priv->cookie + 8 + len, "\r\n", 2);
  166       priv->cookie[10 + len] = '\0';
  167       priv->cookie_len = len + 10;
  168 
  169       if (DBG > 0)
  170     fprintf (stderr, "%s: got cookie `%s'\n", prog_name, start);
  171     }
  172 }
  173 
  174 static void
  175 init (void)
  176 {
  177   Any_Type arg;
  178 
  179   sess_private_data_offset = object_expand (OBJ_SESS,
  180                         sizeof (Sess_Private_Data));
  181   call_private_data_offset = object_expand (OBJ_CALL,
  182                         sizeof (Call_Private_Data));
  183   arg.l = 0;
  184   event_register_handler (EV_CALL_ISSUE, call_issue, arg);
  185   event_register_handler (EV_CALL_RECV_HDR, call_recv_hdr, arg);
  186 }
  187 
  188 Load_Generator sess_cookie =
  189   {
  190     "per-session cookie manager",
  191     init,
  192     no_op,
  193     no_op
  194   };