• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

SpdyCommon.cc

Go to the documentation of this file.
00001 /** @file
00002 
00003   SpdyCommon.cc
00004 
00005   @section license License
00006 
00007   Licensed to the Apache Software Foundation (ASF) under one
00008   or more contributor license agreements.  See the NOTICE file
00009   distributed with this work for additional information
00010   regarding copyright ownership.  The ASF licenses this file
00011   to you under the Apache License, Version 2.0 (the
00012   "License"); you may not use this file except in compliance
00013   with the License.  You may obtain a copy of the License at
00014 
00015       http://www.apache.org/licenses/LICENSE-2.0
00016 
00017   Unless required by applicable law or agreed to in writing, software
00018   distributed under the License is distributed on an "AS IS" BASIS,
00019   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00020   See the License for the specific language governing permissions and
00021   limitations under the License.
00022  */
00023 
00024 #include "SpdyCommon.h"
00025 #include "SpdyCallbacks.h"
00026 
00027 // SPDYlay callbacks
00028 spdylay_session_callbacks spdy_callbacks;
00029 
00030 // statistic names
00031 RecRawStatBlock* spdy_rsb; ///< Container for statistics.
00032 
00033 static char const * const SPDY_STAT_CURRENT_CLIENT_SESSION_NAME = "proxy.process.spdy.current_client_sessions";
00034 static char const * const SPDY_STAT_CURRENT_CLIENT_STREAM_NAME = "proxy.process.spdy.current_client_streams";
00035 static char const * const SPDY_STAT_TOTAL_CLIENT_STREAM_NAME = "proxy.process.spdy.total_client_streams";
00036 static char const * const SPDY_STAT_TOTAL_TRANSACTIONS_TIME_NAME = "proxy.process.spdy.total_transactions_time";
00037 static char const * const SPDY_STAT_TOTAL_CLIENT_CONNECTION_NAME = "proxy.process.spdy.total_client_connections";
00038 
00039 // Configurations
00040 uint32_t spdy_max_concurrent_streams = 100;
00041 uint32_t spdy_initial_window_size = 65536;
00042 int32_t spdy_accept_no_activity_timeout = 120;
00043 int32_t spdy_no_activity_timeout_in = 115;
00044 
00045 string
00046 http_date(time_t t)
00047 {
00048   char buf[32];
00049   tm* tms = gmtime(&t); // returned struct is statically allocated.
00050   size_t r = strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S GMT", tms);
00051   return std::string(&buf[0], &buf[r]);
00052 }
00053 
00054 int
00055 spdy_config_load()
00056 {
00057   REC_EstablishStaticConfigInt32U(spdy_max_concurrent_streams, "proxy.config.spdy.max_concurrent_streams_in");
00058   REC_EstablishStaticConfigInt32U(spdy_initial_window_size, "proxy.config.spdy.initial_window_size_in");
00059   REC_EstablishStaticConfigInt32(spdy_no_activity_timeout_in, "proxy.config.spdy.no_activity_timeout_in");
00060   REC_EstablishStaticConfigInt32(spdy_accept_no_activity_timeout, "proxy.config.spdy.accept_no_activity_timeout");
00061 
00062   spdy_callbacks_init(&spdy_callbacks);
00063 
00064   // Get our statistics up
00065   spdy_rsb = RecAllocateRawStatBlock(static_cast<int>(SPDY_N_STATS));
00066   RecRegisterRawStat(spdy_rsb, RECT_PROCESS, SPDY_STAT_CURRENT_CLIENT_SESSION_NAME, RECD_INT, RECP_NON_PERSISTENT,
00067                      static_cast<int>(SPDY_STAT_CURRENT_CLIENT_SESSION_COUNT), RecRawStatSyncSum);
00068   RecRegisterRawStat(spdy_rsb, RECT_PROCESS, SPDY_STAT_CURRENT_CLIENT_STREAM_NAME, RECD_INT, RECP_NON_PERSISTENT,
00069                      static_cast<int>(SPDY_STAT_CURRENT_CLIENT_STREAM_COUNT), RecRawStatSyncSum);
00070   RecRegisterRawStat(spdy_rsb, RECT_PROCESS, SPDY_STAT_TOTAL_CLIENT_STREAM_NAME, RECD_INT, RECP_PERSISTENT,
00071                      static_cast<int>(SPDY_STAT_TOTAL_TRANSACTIONS_TIME), RecRawStatSyncCount);
00072   RecRegisterRawStat(spdy_rsb, RECT_PROCESS, SPDY_STAT_TOTAL_TRANSACTIONS_TIME_NAME, RECD_INT, RECP_PERSISTENT,
00073                      static_cast<int>(SPDY_STAT_TOTAL_TRANSACTIONS_TIME), RecRawStatSyncSum);
00074   RecRegisterRawStat(spdy_rsb, RECT_PROCESS, SPDY_STAT_TOTAL_CLIENT_CONNECTION_NAME, RECD_INT, RECP_PERSISTENT,
00075                      static_cast<int>(SPDY_STAT_TOTAL_CLIENT_CONNECTION_COUNT), RecRawStatSyncSum);
00076 
00077   return 0;
00078 }
00079 
00080 SpdyNV::SpdyNV(TSFetchSM fetch_sm)
00081 {
00082   int i, len;
00083   char *p;
00084   const char *name, *value;
00085   int name_len, value_len, hdr_len, nr_fields;
00086   TSMLoc loc, field_loc, next_loc;
00087   TSMBuffer bufp;
00088 
00089   bufp = TSFetchRespHdrMBufGet(fetch_sm);
00090   loc = TSFetchRespHdrMLocGet(fetch_sm);
00091 
00092   hdr_len = TSMimeHdrLengthGet(bufp, loc);
00093   mime_hdr = malloc(hdr_len);
00094   TSReleaseAssert(mime_hdr);
00095 
00096   nr_fields = TSMimeHdrFieldsCount(bufp, loc);
00097 
00098   if (nr_fields <= 0) {
00099     Debug("spdy_error", "invalid fetchsm %p, nr_fields %d, hdr_len %d", fetch_sm, nr_fields, hdr_len);
00100   }
00101 
00102   nv = (const char **)malloc((2*nr_fields + 5) * sizeof(char *));
00103   TSReleaseAssert(nv);
00104 
00105   //
00106   // Process Status and Version
00107   //
00108   i = TSHttpHdrVersionGet(bufp, loc);
00109   snprintf(version, sizeof(version), "HTTP/%d.%d", TS_HTTP_MAJOR(i), TS_HTTP_MINOR(i));
00110 
00111   i = TSHttpHdrStatusGet(bufp, loc);
00112   value = (char *)TSHttpHdrReasonGet(bufp, loc, &value_len);
00113   snprintf(status, sizeof(version), "%d ", i);
00114   i = strlen(status);
00115   len = sizeof(status) - i;
00116   len = value_len > len ? len : value_len;
00117   strncpy(&status[i], value, len);
00118   status[len + i] = '\0';;
00119 
00120   i = 0;
00121   nv[i++] = ":version";
00122   nv[i++] = version;
00123   nv[i++] = ":status";
00124   nv[i++] = status;
00125 
00126   //
00127   // Process HTTP headers
00128   //
00129   p = (char *)mime_hdr;
00130   field_loc = TSMimeHdrFieldGet(bufp, loc, 0);
00131   while (field_loc) {
00132     name = TSMimeHdrFieldNameGet(bufp, loc, field_loc, &name_len);
00133     TSReleaseAssert(name && name_len);
00134 
00135     //
00136     // According SPDY v3 spec, in RESPONSE:
00137     // The Connection, Keep-Alive, Proxy-Connection, and
00138     // Transfer-Encoding headers are not valid and MUST not be sent.
00139     //
00140     if (!strncasecmp(name, "Connection", name_len))
00141       goto next;
00142 
00143     if (!strncasecmp(name, "Keep-Alive", name_len))
00144       goto next;
00145 
00146     if (!strncasecmp(name, "Proxy-Connection", name_len))
00147       goto next;
00148 
00149     if (!strncasecmp(name, "Transfer-Encoding", name_len))
00150       goto next;
00151 
00152     value = TSMimeHdrFieldValueStringGet(bufp, loc, field_loc, -1, &value_len);
00153 
00154     //
00155     // Any HTTP headers with empty value are invalid,
00156     // we should ignore them.
00157     //
00158     if (!value || !value_len)
00159       goto next;
00160 
00161     strncpy(p, name, name_len);
00162     nv[i++] = p;
00163     p += name_len;
00164     *p++ = '\0';
00165 
00166     strncpy(p, value, value_len);
00167     nv[i++] = p;
00168     p += value_len;
00169     *p++ = '\0';
00170 
00171 next:
00172     next_loc = TSMimeHdrFieldNext(bufp, loc, field_loc);
00173     TSHandleMLocRelease(bufp, loc, field_loc);
00174     field_loc = next_loc;
00175   }
00176   nv[i] = NULL;
00177 
00178   if (field_loc)
00179     TSHandleMLocRelease(bufp, loc, field_loc);
00180 }
00181 
00182 SpdyNV::~SpdyNV()
00183 {
00184   if (nv)
00185     free(nv);
00186 
00187   if (mime_hdr)
00188     free(mime_hdr);
00189 }

Generated by  doxygen 1.7.1