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

SSLNextProtocolSet.cc

Go to the documentation of this file.
00001 /** @file
00002 
00003   SSLNextProtocolSet
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 "ink_config.h"
00025 #include "apidefs.h"
00026 #include "libts.h"
00027 #include "P_SSLNextProtocolSet.h"
00028 
00029 // For currently defined protocol strings, see
00030 // http://technotes.googlecode.com/git/nextprotoneg.html. The OpenSSL
00031 // documentation tells us to return a string in "wire format". The
00032 // draft NPN RFC helpfuly refuses to document the wire format. The
00033 // above link says we need to send length-prefixed strings, but does
00034 // not say how many bytes the length is. For the record, it's 1.
00035 
00036 unsigned char *
00037 append_protocol(const char * proto, unsigned char * buf)
00038 {
00039   size_t sz = strlen(proto);
00040   *buf++ = (unsigned char)sz;
00041   memcpy(buf, proto, sz);
00042   return buf + sz;
00043 }
00044 
00045 static bool
00046 create_npn_advertisement(
00047   const SSLNextProtocolSet::NextProtocolEndpoint::list_type& endpoints,
00048   unsigned char ** npn, size_t * len)
00049 {
00050   const SSLNextProtocolSet::NextProtocolEndpoint * ep;
00051   unsigned char * advertised;
00052 
00053   *npn = NULL;
00054   *len = 0;
00055 
00056   for (ep = endpoints.head; ep != NULL; ep = endpoints.next(ep)) {
00057     *len += (strlen(ep->protocol) + 1);
00058   }
00059 
00060   *npn = advertised = (unsigned char *)ats_malloc(*len);
00061   if (!(*npn)) {
00062     goto fail;
00063   }
00064 
00065   for (ep = endpoints.head; ep != NULL; ep = endpoints.next(ep)) {
00066     Debug("ssl", "advertising protocol %s", ep->protocol);
00067     advertised = append_protocol(ep->protocol, advertised);
00068   }
00069 
00070   return true;
00071 
00072 fail:
00073   ats_free(*npn);
00074   *npn = NULL;
00075   *len = 0;
00076   return false;
00077 }
00078 
00079 bool
00080 SSLNextProtocolSet::advertiseProtocols(const unsigned char ** out, unsigned * len) const
00081 {
00082   if (npn && npnsz) {
00083     *out = npn;
00084     *len = npnsz;
00085     return true;
00086   }
00087 
00088   return false;
00089 }
00090 
00091 bool
00092 SSLNextProtocolSet::registerEndpoint(const char * proto, Continuation * ep)
00093 {
00094   size_t len = strlen(proto);
00095 
00096   // Both ALPN and NPN only allow 255 bytes of protocol name.
00097   if (len > 255) {
00098     return false;
00099   }
00100 
00101   if (!findEndpoint((const unsigned char *)proto, len)) {
00102     this->endpoints.push(new NextProtocolEndpoint(proto, ep));
00103 
00104     if (npn) {
00105       ats_free(npn);
00106       npn = NULL;
00107       npnsz = 0;
00108     }
00109 
00110     create_npn_advertisement(this->endpoints, &npn, &npnsz);
00111 
00112     return true;
00113   }
00114 
00115   return false;
00116 }
00117 
00118 bool
00119 SSLNextProtocolSet::unregisterEndpoint(const char * proto, Continuation * ep)
00120 {
00121 
00122   for (NextProtocolEndpoint * e = this->endpoints.head;
00123         e; e = this->endpoints.next(e)) {
00124     if (strcmp(proto, e->protocol) == 0 && e->endpoint == ep) {
00125       // Protocol must be registered only once; no need to remove
00126       // any more entries.
00127       this->endpoints.remove(e);
00128       return true;
00129     }
00130   }
00131 
00132   return false;
00133 }
00134 
00135 Continuation *
00136 SSLNextProtocolSet::findEndpoint(
00137   const unsigned char * proto, unsigned len) const
00138 {
00139   for (const NextProtocolEndpoint * ep = this->endpoints.head; ep != NULL; ep = this->endpoints.next(ep)) {
00140     size_t sz = strlen(ep->protocol);
00141     if (sz == len && memcmp(ep->protocol, proto, len) == 0) {
00142       return ep->endpoint;
00143     }
00144   }
00145   return NULL;
00146 }
00147 
00148 SSLNextProtocolSet::SSLNextProtocolSet()
00149   : npn(0), npnsz(0)
00150 {
00151 }
00152 
00153 SSLNextProtocolSet::~SSLNextProtocolSet()
00154 {
00155   ats_free(this->npn);
00156 
00157   for (NextProtocolEndpoint * ep; (ep = this->endpoints.pop());) {
00158     delete ep;
00159   }
00160 }
00161 
00162 SSLNextProtocolSet::NextProtocolEndpoint::NextProtocolEndpoint(
00163         const char * _proto, Continuation * _ep)
00164   : protocol(_proto),  endpoint(_ep)
00165 {
00166 }
00167 
00168 SSLNextProtocolSet::NextProtocolEndpoint::~NextProtocolEndpoint()
00169 {
00170 }

Generated by  doxygen 1.7.1