Webrelay: A Multithreaded HTTP Relay Server
by Peter Zhang 

Listing One
/* Update cookie in the session control data */
int sess_manager_update_cookie(char *seskey, unsigned int keylen, 
                                 accept_info *aip,  relay_info *rip)
{
  chain_node_t *cnp;
  int status;

  cnp = sess_manager_find(seskey, keylen);
  if(cnp != NULL) {
    sess_info_t *sip;

    Spthread_mutex_lock(&cnp->lock);
    sip = (sess_info_t *) cnp->data;
    if(sip != NULL && sip->ClientIPAddr) {
      if ((aip->cliaddr->sin_addr.s_addr == sip->ClientIPAddr)) {
        time_t ct;
        time(&ct);
        if ( difftime(ct, cnp->LastUpdated) <= sess_manager_refresh ) {
          char *cookie_cookie = NULL;
          char *cookie_name = NULL;
          char *cookie_path = NULL;
          char *cookie_domain = NULL;
          char *p;
          int i, j, len1, len2;
          /* Session still valid.*/
          cnp->LastUpdated = ct;

          /* rip->cookie: NAME=VALUE; PATH=/path1/path2, while
             cookie_cookie contains NAME=VALUE, and cookie_path
             is /path1/path2 */
          cookie_cookie = 
               parse_cookie(rip->cookie, &cookie_path, &cookie_domain);
          if ((p = strchr(cookie_cookie, '=')) != NULL) 
            /* cookie_name is NAME */
            cookie_name = strdupdelim(cookie_cookie, p);

          if(sip->cookie_path[0] == NULL && sip->cookie_name[0] == NULL &&
             sip->cookie_value[0] == NULL) {
            /* There is no existing cookies in the SIP yet. Simply insert
               the new cookie into it. */
            sip->cookie_path[0] = xstrdup(cookie_path);
            sip->cookie_name[0] = xstrdup(cookie_name);
            sip->cookie_domain[0] = xstrdup(cookie_domain);
            sip->cookie_value[0] = xstrdup(cookie_cookie);
          } else {
            /* Match the existing cookies already stored in SIP */
            for(i=0; i<MAX_NUM_COOKIE && sip->cookie_path[i] != NULL; ++i) {
              len1 = strlen(cookie_path);
              if(!strncasecmp(cookie_path, sip->cookie_path[i], len1)) {
               for (j=i; j<MAX_NUM_COOKIE && sip->cookie_name[j]!=NULL;++j
) {
                  len2 = strlen(cookie_name);
                  if(!strncasecmp(cookie_name, sip->cookie_name[j], len2) &&
                     !strncasecmp(cookie_path, sip->cookie_path[j], len1)) {
                    /* Overwrite this cookie */
                    FREE_MAYBE(sip->cookie_value[j]);
                    /* We store NAME=VALUE together as one single cookie */
                    sip->cookie_value[j] = xstrdup(cookie_cookie);
                    break;
                  }
                }
                /* No match of cookie_name, regarded as a new cookie of 
                   the same path. Now we ADD this new cookie at j */
                sip->cookie_path[j] = xstrdup(cookie_path);
                sip->cookie_name[j] = xstrdup(cookie_name);
                sip->cookie_domain[j] = xstrdup(cookie_domain);
                sip->cookie_value[j] = xstrdup(cookie_cookie);
                break;
              } 
            }
            if (sip->cookie_path[i] == NULL && sip->cookie_name[i] == NULL) {
              /* No match either of cookie_name nor cookie_path. 
                 This is a new cookie of 
                 a new path. Now we add this new cookie at i */
              sip->cookie_path[i] = xstrdup(cookie_path);
              sip->cookie_name[i] = xstrdup(cookie_name);
              sip->cookie_domain[i] = xstrdup(cookie_domain);
              sip->cookie_value[i] = xstrdup(cookie_cookie);
            }
          }
          FREE_MAYBE(cookie_name);
          FREE_MAYBE(cookie_path);
          FREE_MAYBE(cookie_domain);
          FREE_MAYBE(cookie_cookie);

          cnp->data = (void *) sip;
          status = SES_OK;
        } else
          status = SES_TIMEOUT;
      } else
        status = SES_CLIENT_ENDS;
    } else 
      status = SES_CLIENT_ENDS;
    Spthread_mutex_unlock(&cnp->lock);
    chain_hash_release(cnp);
  } else
    status = SES_CLIENT_ENDS;
  return status;
}


Listing Two
/* Retrieve cookie from session control data */
int sess_manager_retrieve_cookie(char *seskey, unsigned int keylen,
                             accept_info *aip, relay_info *rip)
{
  int i, len1, len2, len;
  chain_node_t *cnp;
  int status;

  cnp = sess_manager_find(seskey, keylen);
  if(cnp != NULL) {
    sess_info_t *sip;
    Spthread_mutex_lock(&cnp->lock);
    sip = (sess_info_t *) cnp->data;
    if(sip != NULL && sip->ClientIPAddr) {
      if ((aip->cliaddr->sin_addr.s_addr == sip->ClientIPAddr)) {
        time_t ct;
        time(&ct);
        if ( difftime(ct, cnp->LastUpdated) <= sess_manager_refresh ) {
          char *targethost = NULL;
          char *targetpath = NULL;
          int i, len, len1, len2, old_len, num_entries;
          int ck_dom_len, targethost_len;

          /* Session still valid.*/
          if(rip->redir_targethost != NULL)
            targethost = xstrdup(rip->redir_targethost);
          else
            targethost = xstrdup(rip->targethost);
          if(rip->redir_targetpath != NULL)
            targetpath = xstrdup(rip->redir_targetpath);
          else
            targetpath = xstrdup(rip->targetpath);
          FREE_MAYBE(rip->cookie);
          old_len = 0;
          num_entries = 0;
          for(i = 0;i<MAX_NUM_COOKIE && sip->cookie_path[i] != NULL; ++i) {
            /* First match the domain */
            targethost_len = strlen(targethost);
            if(sip->cookie_domain[i] != NULL)
              ck_dom_len = strlen(sip->cookie_domain[i]);
            else
              goto Match_path;

            /* Consume chars one by one from the end of the cookie_domain */
            while(--ck_dom_len >= 0 && --targethost_len >= 0) {
              if(sip->cookie_domain[i][ck_dom_len] != 
                                                 targethost[targethost_len])
                break;
            }
            if(ck_dom_len > 0) {
              /* No match of domain, search the next entry */
              continue;
            }
            /* Match the path */
          Match_path:
            len1 = (strlen(sip->cookie_path[i]) < strlen(targetpath)) ?
              strlen(sip->cookie_path[i]) : strlen(targetpath);
            if(!strncasecmp(targetpath, sip->cookie_path[i], len1)) {
              num_entries++;
              len2 = strlen(sip->cookie_value[i]);

              if(num_entries == 1) {
               len = len2;
               rip->cookie = Smalloc(len);
               memcpy(rip->cookie, sip->cookie_value[i], len);
             } else {
               len = old_len + 1 + 1 + len2;
               rip->cookie = Srealloc(rip->cookie, len);
               memcpy(rip->cookie + old_len, "; ", 2);
               memcpy(rip->cookie + old_len + 2, sip->cookie_value[i], len2);
              }
              old_len = len;
            }
          }
          if(num_entries > 0) {
            rip->cookie = Srealloc(rip->cookie, len + 1);
            rip->cookie[len] = '\0';
          }
          FREE_MAYBE(targethost);
          FREE_MAYBE(targetpath);
          status = SES_OK;
        } else {
          status = SES_TIMEOUT;
        }
      } else
        status = SES_CLIENT_ENDS;
    } else 
      status = SES_CLIENT_ENDS;
    Spthread_mutex_unlock(&cnp->lock);
    chain_hash_release(cnp);
  } else
    status = SES_CLIENT_ENDS;
  return status;
}







1


