Repository: trafficserver
Updated Branches:
  refs/heads/master aaf5d6bfa -> 5f2fc30d7


TS-3219: Separate WCCP client process


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/5f2fc30d
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/5f2fc30d
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/5f2fc30d

Branch: refs/heads/master
Commit: 5f2fc30d7d1b4f2107026ede93c05df8360e4d75
Parents: aaf5d6b
Author: shinrich <shinr...@network-geographics.com>
Authored: Thu Nov 20 15:14:55 2014 -0600
Committer: shinrich <shinr...@yahoo-inc.com>
Committed: Thu Jan 8 13:54:10 2015 -0600

----------------------------------------------------------------------
 CHANGES                                        |   2 +
 lib/wccp/Makefile.am                           |   8 +-
 lib/wccp/Wccp.h                                |   2 +-
 lib/wccp/WccpConfig.cc                         |  11 +
 lib/wccp/WccpEndPoint.cc                       | 139 +++++++----
 lib/wccp/WccpLocal.h                           |  17 ++
 lib/wccp/wccp-test-cache.cc                    | 196 ---------------
 lib/wccp/wccp-test-router.cc                   |  14 +-
 tools/Makefile.am                              |  17 +-
 tools/wccp_client/Makefile.am                  |  33 +++
 tools/wccp_client/readme.txt                   |  42 ++++
 tools/wccp_client/service-nogre-example.config |  66 +++++
 tools/wccp_client/wccp_client.cc               | 256 ++++++++++++++++++++
 13 files changed, 544 insertions(+), 259 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/5f2fc30d/CHANGES
----------------------------------------------------------------------
diff --git a/CHANGES b/CHANGES
index eac1de9..3b06244 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,8 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache Traffic Server 5.3.0
 
+  *) [TS-3219] Create WCCP client process.
+
   *) [TS-3272] Fix to ensure that SSL_SNI callback only called when state
    changes.
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/5f2fc30d/lib/wccp/Makefile.am
----------------------------------------------------------------------
diff --git a/lib/wccp/Makefile.am b/lib/wccp/Makefile.am
index f782c8b..abbf632 100644
--- a/lib/wccp/Makefile.am
+++ b/lib/wccp/Makefile.am
@@ -26,7 +26,7 @@ AM_CPPFLAGS = \
 #DEFS += $(WCCP_DEFS)
 
 noinst_LIBRARIES = libwccp.a
-#noinst_PROGRAMS = test-cache
+# noinst_PROGRAMS = test-cache 
 
 libwccp_a_SOURCES = \
   Wccp.h \
@@ -38,5 +38,7 @@ libwccp_a_SOURCES = \
   WccpStatic.cc \
   WccpUtil.h
 
-#test_cache_SOURCES = \
-#  wccp-test-cache.cc wccp-test-router.cc
+# test_cache_SOURCES = \
+#   wccp-test-cache.cc
+
+# test_cache_LDADD = $(LDADD) -L$(top_builddir)/lib/tsconfig -ltsconfig 
-L$(top_builddir)/lib/wccp -lwccp -L$(top_builddir)/lib/ts -ltsutil

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/5f2fc30d/lib/wccp/Wccp.h
----------------------------------------------------------------------
diff --git a/lib/wccp/Wccp.h b/lib/wccp/Wccp.h
index 4e885e5..cfe99c7 100644
--- a/lib/wccp/Wccp.h
+++ b/lib/wccp/Wccp.h
@@ -27,6 +27,7 @@
 # include <tsconfig/Errata.h>
 # include <memory.h>
 # include <ink_defs.h>
+# include <ink_memory.h>
 // Nasty, defining this with no prefix. The value is still available
 // in TS_VERSION_STRING.
 # undef VERSION
@@ -421,7 +422,6 @@ inline ServiceGroup::Type
 ServiceGroup::getSvcType() const {
   return static_cast<ServiceGroup::Type>(m_svc_type);
 }
-
 inline uint8_t
 ServiceGroup::getSvcId() const {
   return m_svc_id;

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/5f2fc30d/lib/wccp/WccpConfig.cc
----------------------------------------------------------------------
diff --git a/lib/wccp/WccpConfig.cc b/lib/wccp/WccpConfig.cc
index 443fa8f..fca9966 100644
--- a/lib/wccp/WccpConfig.cc
+++ b/lib/wccp/WccpConfig.cc
@@ -67,6 +67,7 @@ static char const * const SVC_PROP_ROUTERS = "routers";
 static char const * const SVC_PROP_FORWARD = "forward";
 static char const * const SVC_PROP_RETURN = "return";
 static char const * const SVC_PROP_ASSIGN = "assignment";
+static char const * const SVC_PROP_PROC = "proc-name";
 
 static char const * const SECURITY_PROP_OPTION = "option";
 static char const * const SECURITY_PROP_KEY = "key";
@@ -725,6 +726,16 @@ CacheImpl::loadServicesFromFile(char const* path) {
 
     // Properties after this are optional so we can proceed if they fail.
     GroupData& svc = this->defineServiceGroup(svc_info);
+
+    // Is there a process we should track?
+    if ((prop = svc_cfg[SVC_PROP_PROC]).hasValue()) {
+      if (ts::config::StringValue == prop.getType()) {
+         svc.setProcName(prop.getText());
+      } else {
+        zret.push(Prop_Invalid_Type(prop, ts::config::StringValue));
+      }
+    } 
+
     // Add seed routers.
     std::vector<uint32_t>::iterator rspot, rlimit;
     for ( rspot = routers.begin(), rlimit = routers.end() ; rspot != rlimit ; 
++rspot )

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/5f2fc30d/lib/wccp/WccpEndPoint.cc
----------------------------------------------------------------------
diff --git a/lib/wccp/WccpEndPoint.cc b/lib/wccp/WccpEndPoint.cc
index 0dcf7cb..2426bc1 100644
--- a/lib/wccp/WccpEndPoint.cc
+++ b/lib/wccp/WccpEndPoint.cc
@@ -255,7 +255,7 @@ Impl::handleRemovalQuery(IpHeader const&, ts::Buffer const& 
/* data ATS_UNUSED *
 }
 // ------------------------------------------------------
 CacheImpl::GroupData::GroupData()
-  : m_assignment_pending(false) {
+  : m_proc_name(NULL), m_assignment_pending(false) {
 }
 
 CacheImpl::GroupData&
@@ -404,6 +404,37 @@ CacheImpl::GroupData::waitTime(time_t now) const {
 }
 
 bool
+CacheImpl::GroupData::processUp() {
+  bool zret = false;
+  const char *proc_pid_path = this->getProcName();
+  if (proc_pid_path == NULL || proc_pid_path[0] == '\0') {
+    zret = true; // No process to track, always chatter
+  } else {
+    // Look for the pid file
+    int fd = open(proc_pid_path, O_RDONLY);
+    if (fd > 0) {
+      char buffer[256];
+      ssize_t read_count = read(fd, buffer, sizeof(buffer)-1);
+      close(fd);
+      if (read_count > 0) {
+        buffer[read_count] = '\0';
+        int pid = atoi(buffer);
+        if (pid > 0) {
+          // If the process is still running, it has an entry in the proc file 
system, (Linux only)
+          sprintf(buffer, "/proc/%d/status", pid);
+          fd = open(buffer, O_RDONLY);
+          if (fd > 0) {
+            zret = true;
+            close(fd); 
+          }
+        }
+      }
+    }
+  }
+  return zret;
+}
+
+bool
 CacheImpl::GroupData::cullRouters(time_t now) {
   bool zret = false;
   size_t idx = 0, n = m_routers.size();
@@ -603,37 +634,40 @@ CacheImpl::housekeeping() {
 
     group.cullRouters(now); // TBD UPDATE VIEW!
 
-    // Check the active routers for scheduled packets.
-    for ( RouterBag::iterator rspot = group.m_routers.begin(),
-             rend = group.m_routers.end() ;
-           rspot != rend ;
-           ++rspot
-    ) {
-      dst_addr.sin_addr.s_addr = rspot->m_addr;
-      if (0 == rspot->pingTime(now)) {
-        HereIAmMsg here_i_am;
-        here_i_am.setBuffer(msg_buffer);
-        this->generateHereIAm(here_i_am, group, *rspot);
-        zret = sendto(m_fd, msg_data, here_i_am.getCount(), 0, addr_ptr, 
sizeof(dst_addr));
-        if (0 <= zret) {
-          rspot->m_xmit.set(now, group.m_generation);
-          rspot->m_send_caps = false;
-          logf(LVL_DEBUG, "Sent HERE_I_AM for service group %d to router 
%s%s[#%d,%lu].",
-            group.m_svc.getSvcId(),
-            ip_addr_to_str(rspot->m_addr),
-            rspot->m_rapid ? " [rapid] " : " ",
-            group.m_generation, now
-          );
-          if (rspot->m_rapid) --(rspot->m_rapid);
-        } else {
-          logf_errno(LVL_WARN, "Failed to send to router " ATS_IP_PRINTF_CODE 
" - ", ATS_IP_OCTETS(rspot->m_addr));
+    // Check to see if the related service is up
+    if (group.processUp()) {
+      // Check the active routers for scheduled packets.
+      for ( RouterBag::iterator rspot = group.m_routers.begin(),
+               rend = group.m_routers.end() ;
+             rspot != rend ;
+             ++rspot
+      ) {
+        dst_addr.sin_addr.s_addr = rspot->m_addr;
+        if (0 == rspot->pingTime(now)) {
+          HereIAmMsg here_i_am;
+          here_i_am.setBuffer(msg_buffer);
+          this->generateHereIAm(here_i_am, group, *rspot);
+          zret = sendto(m_fd, msg_data, here_i_am.getCount(), 0, addr_ptr, 
sizeof(dst_addr));
+          if (0 <= zret) {
+            rspot->m_xmit.set(now, group.m_generation);
+            rspot->m_send_caps = false;
+            logf(LVL_DEBUG, "Sent HERE_I_AM for service group %d to router 
%s%s[#%d,%lu].",
+              group.m_svc.getSvcId(),
+              ip_addr_to_str(rspot->m_addr),
+              rspot->m_rapid ? " [rapid] " : " ",
+              group.m_generation, now
+            );
+            if (rspot->m_rapid) --(rspot->m_rapid);
+          } else {
+            logf_errno(LVL_WARN, "Failed to send to router " 
ATS_IP_PRINTF_CODE " - ", ATS_IP_OCTETS(rspot->m_addr));
+          }
+        } else if (rspot->m_assign) {
+          RedirectAssignMsg redirect_assign;
+          redirect_assign.setBuffer(msg_buffer);
+          this->generateRedirectAssign(redirect_assign, group);
+          zret = sendto(m_fd, msg_data, redirect_assign.getCount(), 0, 
addr_ptr, sizeof(dst_addr));
+          if (0 <= zret) rspot->m_assign = false;
         }
-      } else if (rspot->m_assign) {
-        RedirectAssignMsg redirect_assign;
-        redirect_assign.setBuffer(msg_buffer);
-        this->generateRedirectAssign(redirect_assign, group);
-        zret = sendto(m_fd, msg_data, redirect_assign.getCount(), 0, addr_ptr, 
sizeof(dst_addr));
-        if (0 <= zret) rspot->m_assign = false;
       }
     }
 
@@ -644,32 +678,35 @@ CacheImpl::housekeeping() {
            sspot != slimit ;
            ++sspot
     ) {
-      HereIAmMsg here_i_am;
-      here_i_am.setBuffer(msg_buffer);
-      // Is the router due for a ping?
-      if (sspot->m_xmit + TIME_UNIT > now) continue; // no
+      // Check to see if the related service is up
+      if (group.processUp()) {
+        HereIAmMsg here_i_am;
+        here_i_am.setBuffer(msg_buffer);
+        // Is the router due for a ping?
+        if (sspot->m_xmit + TIME_UNIT > now) continue; // no
 
-      this->generateHereIAm(here_i_am, group);
+        this->generateHereIAm(here_i_am, group);
 
-      dst_addr.sin_addr.s_addr = sspot->m_addr;
-      zret = sendto(m_fd, msg_data, here_i_am.getCount(), 0,
-        addr_ptr, sizeof(dst_addr));
-      if (0 <= zret) {
-        logf(LVL_DEBUG, "Sent HERE_I_AM for SG %d to seed router %s 
[gen=#%d,t=%lu,n=%lu].",
+        dst_addr.sin_addr.s_addr = sspot->m_addr;
+        zret = sendto(m_fd, msg_data, here_i_am.getCount(), 0,
+          addr_ptr, sizeof(dst_addr));
+        if (0 <= zret) {
+          logf(LVL_DEBUG, "Sent HERE_I_AM for SG %d to seed router %s 
[gen=#%d,t=%lu,n=%lu].",
+            group.m_svc.getSvcId(),
+            ip_addr_to_str(sspot->m_addr),
+            group.m_generation, now, here_i_am.getCount()
+          );
+          sspot->m_xmit = now;
+          sspot->m_count += 1;
+        }
+        else logf(LVL_DEBUG,
+          "Error [%d:%s] sending HERE_I_AM for SG %d to seed router %s 
[#%d,%lu].",
+          zret, strerror(errno),
           group.m_svc.getSvcId(),
           ip_addr_to_str(sspot->m_addr),
-          group.m_generation, now, here_i_am.getCount()
+          group.m_generation, now
         );
-        sspot->m_xmit = now;
-        sspot->m_count += 1;
       }
-      else logf(LVL_DEBUG,
-        "Error [%d:%s] sending HERE_I_AM for SG %d to seed router %s 
[#%d,%lu].",
-        zret, strerror(errno),
-        group.m_svc.getSvcId(),
-        ip_addr_to_str(sspot->m_addr),
-        group.m_generation, now
-      );
     }
   }
   return zret;

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/5f2fc30d/lib/wccp/WccpLocal.h
----------------------------------------------------------------------
diff --git a/lib/wccp/WccpLocal.h b/lib/wccp/WccpLocal.h
index 9d73d17..89bab24 100644
--- a/lib/wccp/WccpLocal.h
+++ b/lib/wccp/WccpLocal.h
@@ -2463,10 +2463,12 @@ namespace detail {
       /// Cache assignment methods supported.
       ServiceGroup::CacheAssignmentStyle m_cache_assign;
 
+
       /// Known caches.
       CacheBag m_caches;
       /// Known routers.
       RouterBag m_routers;
+      char *m_proc_name;
 
       /// Set if there an assignment should be computed and sent.
       /// This is before checking for being a designated cache
@@ -2478,6 +2480,9 @@ namespace detail {
 
       GroupData(); ///< Default constructor.
 
+      void setProcName(const ts::ConstBuffer &name);
+      const char *getProcName();
+
       /// Find a router by IP @a addr.
       /// @return A pointer to the router, or @c NULL if not found.
       RouterBag::iterator findRouter(
@@ -2518,6 +2523,10 @@ namespace detail {
         time_t now ///< Current time.
       );
 
+      /** Check to see if the process associated with service is up
+      */
+      bool processUp();
+
       /// Update state to reflect a view change.
       self& viewChanged(time_t now);
 
@@ -2530,6 +2539,14 @@ namespace detail {
         SecurityOption style ///< Security style to use.
       );
     };
+    inline const char *
+    GroupData::getProcName() {
+      return m_proc_name;
+    }
+    inline void
+    GroupData::setProcName(const ts::ConstBuffer &name) {
+      m_proc_name = ats_strndup(name.data(), name.size());
+    }
   }
 }
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/5f2fc30d/lib/wccp/wccp-test-cache.cc
----------------------------------------------------------------------
diff --git a/lib/wccp/wccp-test-cache.cc b/lib/wccp/wccp-test-cache.cc
deleted file mode 100644
index f044dc8..0000000
--- a/lib/wccp/wccp-test-cache.cc
+++ /dev/null
@@ -1,196 +0,0 @@
-/** @file
-    WCCP cache simulation for testing.
-
-    @section license License
-
-    Licensed to the Apache Software Foundation (ASF) under one
-    or more contributor license agreements.  See the NOTICE file
-    distributed with this work for additional information
-    regarding copyright ownership.  The ASF licenses this file
-    to you under the Apache License, Version 2.0 (the
-    "License"); you may not use this file except in compliance
-    with the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- */
-
-# include <stdio.h>
-# include <unistd.h>
-# include <stdarg.h>
-# include <memory.h>
-# include <strings.h>
-# include <iostream>
-# include <iomanip>
-
-# include <getopt.h>
-
-# include "Wccp.h"
-
-# include <sys/socket.h>
-# include <netinet/in.h>
-# include <arpa/inet.h>
-
-# include <poll.h>
-
-# include <libconfig.h++>
-
-static char const USAGE_TEXT[] =
-  "%s\n"
-  "--address IP address to bind.\n"
-  "--router Booststrap IP address for routers.\n"
-  "--service Path to service group definitions.\n"
-  "--help Print usage and exit.\n"
-  ;
-
-static bool Ready = true;
-
-inline void Error(char const* fmt, ...) {
-  va_list args;
-  va_start(args, fmt);
-  vfprintf(stderr, fmt, args);
-  Ready = false;
-}
-
-void Log(
-  std::ostream& out,
-  ats::Errata const& errata,
-  int indent = 0
-) {
-  for ( ats::Errata::const_iterator spot = errata.begin(), limit = 
errata.end();
-        spot != limit;
-        ++spot
-  ) {
-    if (spot->m_id) {
-      if (indent) out << std::setw(indent) << std::setfill(' ') << "> ";
-      out << spot->m_id << " [" << spot->m_code << "]: " << spot->m_text
-          << std::endl
-        ;
-    }
-    if (spot->getErrata().size()) Log(out, spot->getErrata(), indent+2);
-  }
-}
-
-void LogToStdErr(ats::Errata const& errata) {
-  Log(std::cerr, errata);
-}
-
-int
-main(int argc, char** argv) {
-  Wccp::Cache wcp;
-
-  // Reading stdin support.
-  size_t in_size = 200;
-  char* in_buff = 0;
-  ssize_t in_count;
-
-  // Set up erratum support.
-  ats::Errata::registerSink(&LogToStdErr);
-
-  // getopt return values. Selected to avoid collisions with
-  // short arguments.
-  static int const OPT_ADDRESS = 257; ///< Bind to IP address option.
-  static int const OPT_HELP = 258; ///< Print help message.
-  static int const OPT_ROUTER = 259; ///< Seeded router IP address.
-  static int const OPT_SERVICE = 260; ///< Service group definition.
-
-  static option OPTIONS[] = {
-    { "address", 1, 0, OPT_ADDRESS },
-    { "router", 1, 0, OPT_ROUTER },
-    { "service", 1, 0, OPT_SERVICE },
-    { "help", 0, 0, OPT_HELP },
-    { 0, 0, 0, 0 } // required terminator.
-  };
-
-  in_addr ip_addr = { INADDR_ANY };
-  in_addr router_addr = { INADDR_ANY };
-
-  int zret; // getopt return.
-  int zidx; // option index.
-  bool fail = false;
-  char const* FAIL_MSG = "";
-
-  while (-1 != (zret = getopt_long_only(argc, argv, "", OPTIONS, &zidx))) {
-    switch (zret) {
-    case OPT_HELP:
-      FAIL_MSG = "Usage:";
-      fail = true;
-      break;
-    case '?':
-      FAIL_MSG = "Invalid option specified.";
-      fail = true;
-      break;
-    case OPT_ADDRESS:
-      if (0 == inet_aton(optarg, &ip_addr)) {
-        FAIL_MSG = "Invalid IP address specified for client.";
-        fail = true;
-      }
-      break;
-    case OPT_ROUTER:
-      if (0 == inet_aton(optarg, &router_addr)) {
-        FAIL_MSG = "Invalid IP address specified for router.";
-        fail = true;
-      }
-      break;
-    case OPT_SERVICE:
-      ats::Errata status = wcp.loadServicesFromFile(optarg);
-      if (!status) fail = true;
-      break;
-    }
-  }
-
-  if (fail) {
-    printf(USAGE_TEXT, FAIL_MSG);
-    return 1;
-  }
-
-  if (0 > wcp.open(ip_addr.s_addr)) {
-    fprintf(stderr, "Failed to open or bind socket.\n");
-    return 2;
-  }
-
-  static int const POLL_FD_COUNT = 2;
-  pollfd pfa[POLL_FD_COUNT];
-
-  // Poll on STDIN and the socket.
-  pfa[0].fd = STDIN_FILENO;
-  pfa[0].events = POLLIN;
-
-  pfa[1].fd = wcp.getSocket();
-  pfa[1].events = POLLIN;
-
-  wcp.housekeeping();
-
-  while (true) {
-    time_t dt = std::min(Wccp::TIME_UNIT, wcp.waitTime());
-    printf("Waiting %lu milliseconds\n", dt * 1000);
-    int n = poll(pfa, POLL_FD_COUNT, dt * 1000);
-    if (n < 0) { // error
-      perror("General polling failure");
-      return 5;
-    } else if (n > 0) { // things of interest happened
-      if (pfa[1].revents) {
-        if (pfa[1].revents & POLLIN) {
-          wcp.handleMessage();
-        } else {
-          fprintf(stderr, "Socket failure.\n");
-          return 6;
-        }
-      }
-      if (pfa[0].revents) {
-        if (pfa[0].revents & POLLIN) {
-          in_count = getline(&in_buff, &in_size, stdin);
-          fprintf(stderr, "Terminated from console.\n");
-          return 0;
-        }
-      }
-    } else { // timeout
-      wcp.housekeeping();
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/5f2fc30d/lib/wccp/wccp-test-router.cc
----------------------------------------------------------------------
diff --git a/lib/wccp/wccp-test-router.cc b/lib/wccp/wccp-test-router.cc
index 731cd41..362277b 100644
--- a/lib/wccp/wccp-test-router.cc
+++ b/lib/wccp/wccp-test-router.cc
@@ -28,7 +28,7 @@
 
 # include <getopt.h>
 
-# include "ats-wccp-api.h"
+# include "Wccp.h"
 
 # include <sys/socket.h>
 # include <netinet/in.h>
@@ -36,7 +36,7 @@
 
 # include <poll.h>
 
-# include <libconfig.h++>
+# include <tsconfig/TsValue.h>
 
 static char const USAGE_TEXT[] =
   "%s\n"
@@ -55,7 +55,7 @@ inline void Error(char const* fmt, ...) {
 
 int
 main(int argc, char** argv) {
-  Wccp::Router wcp;
+  wccp::Router wcp;
 
   // Reading stdin support.
   size_t in_size = 200;
@@ -124,11 +124,11 @@ main(int argc, char** argv) {
   pfa[0].fd = STDIN_FILENO;
   pfa[0].events = POLLIN;
 
-  pfa[1].fd = wcp.get_socket();
+  pfa[1].fd = wcp.getSocket();
   pfa[1].events = POLLIN;
 
   while (true) {
-    int n = poll(pfa, POLL_FD_COUNT, Wccp::TIME_UNIT * 1000);
+    int n = poll(pfa, POLL_FD_COUNT, wccp::TIME_UNIT * 1000);
     if (n < 0) { // error
       perror("General polling failure");
       return 5;
@@ -136,7 +136,7 @@ main(int argc, char** argv) {
       if (pfa[1].revents) {
         if (pfa[1].revents & POLLIN) {
           wcp.handleMessage();
-          wcp.sendPendingMessages();
+          //wcp.sendPendingMessages();
         } else {
           fprintf(stderr, "Socket failure.\n");
           return 6;
@@ -150,7 +150,7 @@ main(int argc, char** argv) {
         }
       }
     } else { // timeout
-      wcp.sendPendingMessages();
+      //wcp.sendPendingMessages();
     }
   }
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/5f2fc30d/tools/Makefile.am
----------------------------------------------------------------------
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 56726b8..4b04473 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -22,7 +22,8 @@ bin_SCRIPTS = tsxs tspush
 AM_LDFLAGS = @EXTRA_CXX_LDFLAGS@ @LIBTOOL_LINK_FLAGS@
 AM_CPPFLAGS = $(iocore_include_dirs) \
   -I$(top_srcdir)/lib -I$(top_builddir)/lib \
-  -I$(top_srcdir)/lib/ts -I$(top_builddir)/lib/ts
+  -I$(top_srcdir)/lib/ts -I$(top_builddir)/lib/ts \
+  -I$(top_srcdir)/lib/wccp
 
 if BUILD_TEST_TOOLS
 bin_PROGRAMS = jtest/jtest
@@ -49,3 +50,17 @@ http_load_http_load_SOURCES =  \
   http_load/timers.h
 
 endif
+
+if BUILD_WCCP 
+
+if BUILD_TEST_TOOLS
+bin_PROGRAMS += wccp_client/wccp_client
+else
+bin_PROGRAMS = wccp_client/wccp_client
+endif
+
+wccp_client_wccp_client_SOURCES = wccp_client/wccp_client.cc
+
+wccp_client_wccp_client_LDADD = -L$(top_builddir)/lib/tsconfig -ltsconfig 
-L$(top_builddir)/lib/wccp -lwccp -L$(top_builddir)/lib/ts -ltsutil
+
+endif

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/5f2fc30d/tools/wccp_client/Makefile.am
----------------------------------------------------------------------
diff --git a/tools/wccp_client/Makefile.am b/tools/wccp_client/Makefile.am
new file mode 100644
index 0000000..969d67c
--- /dev/null
+++ b/tools/wccp_client/Makefile.am
@@ -0,0 +1,33 @@
+#
+# Makefile.am for WCCP client
+#
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+
+AM_CPPFLAGS = \
+  -I$(top_srcdir)/lib \
+  -I$(top_srcdir)/lib/ts \
+  -I$(top_srcdir)/proxy/api/ts
+
+#WCCP_DEFS = @WCCP_DEFS@
+#DEFS += $(WCCP_DEFS)
+
+noinst_PROGRAMS = test-cache 
+
+test_cache_SOURCES = \
+  wccp-test-cache.cc
+
+test_cache_LDADD = $(LDADD) -L$(top_builddir)/lib/tsconfig -ltsconfig 
-L$(top_builddir)/lib/wccp -lwccp -L$(top_builddir)/lib/ts -ltsutil

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/5f2fc30d/tools/wccp_client/readme.txt
----------------------------------------------------------------------
diff --git a/tools/wccp_client/readme.txt b/tools/wccp_client/readme.txt
new file mode 100644
index 0000000..d86e8c3
--- /dev/null
+++ b/tools/wccp_client/readme.txt
@@ -0,0 +1,42 @@
+Wccp_client is a front end to the wccp client library.  It is a stand
+alone program that speaks the client side of the WCCP cache protocol.
+
+It can be used instead of the built in WCCP feature in Apache traffic server.
+This can be beneficial if you have multiple programs running on the same
+computer that are relying on WCCP to redirect traffic from the router to 
+the computer.
+
+Since it relies on the wccp library, the wccp_client is only build if apache
+traffic server is configured with --enable-wccp.
+
+The overall Apache Traffic Server WCCP configuration documentation is
+at 
https://docs.trafficserver.apache.org/en/latest/admin/transparent-proxy/wccp-configuration.en.html.
+
+The wccp-client takes the following arguments. 
+--address IP address to bind.
+--router Booststrap IP address for routers.
+--service Path to service group definitions.
+--debug Print debugging information.
+--daemon Run as daemon.
+
+You need to run at least with the --address and the --service arguments. The
+address should be an address assigned to one of your computer's interfaces.
+An example service definition file, service-nogre-example.config, is included
+in this directory.  In this file you define your MD5 security password
+(highly recommended), and you define your service groups.  For each service
+group you define how the service should be recognized (protocol and port),
+the routers you are communicating with, whether you are using GRE or basic L2
+routing to redirect packets.  
+
+In addition, you can specify a proc-name, a path
+to a process pid file.  If the proc-name is present, the wccp client will 
+only advertise the associated service group, if the process is currently 
+up and running.  So if your computer is hosting three services, and one of
+them goes down, the wccp client could stop advertising the service group 
+associated with the down service thus stopping the router from redirecting
+that traffic, but continue to advertise and maintain the redireciton for the
+other two services.
+
+The current WCCP implementation associated with ATS only supports one cache
+client per service group per router.  The cache assignment logic current
+assigns the current cache client to all buckets.  

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/5f2fc30d/tools/wccp_client/service-nogre-example.config
----------------------------------------------------------------------
diff --git a/tools/wccp_client/service-nogre-example.config 
b/tools/wccp_client/service-nogre-example.config
new file mode 100644
index 0000000..56152b5
--- /dev/null
+++ b/tools/wccp_client/service-nogre-example.config
@@ -0,0 +1,66 @@
+security = {
+  key = "example-password";
+  option = "MD5";
+};
+
+services = (
+  {
+    name = "WCCP HTTP Client";
+    description = "Capture packets from client";
+    proc-name = "/opt/ats/var/trafficserver/cop.lock";
+    id = 51;
+    type = "DYNAMIC";
+    priority = 240;
+    protocol = 6;
+    primary-hash = ( "src_ip" );
+    ports = ( 80 );
+    assignment = ( "hash" );
+    forward = ( "l2" );
+    return = ( "l2" );
+    routers = ( "10.10.50.1" );
+  },
+  {
+    name = "WCCP HTTP Server";
+    description = "Capture packets from origin server";
+    proc-name = "/opt/ats/var/trafficserver/cop.lock";
+    id = 52;
+    type = "DYNAMIC";
+    priority = 240;
+    protocol = 6;
+    primary-hash = ( "dst_ip" );
+    ports = ( 80 );
+    port-type = "src";
+    assignment = ( "hash" );
+    forward = ( "l2" );
+    return = ( "l2" );
+    routers = ( "10.10.50.1" );
+  },
+  {
+    name = "WCCP RTMP Client";
+    description = "Capture packets from client";
+    id = 53;
+    type = "DYNAMIC";
+    priority = 240;
+    protocol = 6;
+    primary-hash = ( "src_ip" );
+    ports = ( 1935 );
+    assignment = ( "hash" );
+    forward = ( "l2" );
+    return = ( "l2" );
+    routers = ( "10.10.50.1" );
+  },
+  {
+    name = "WCCP RTSP Client";
+    description = "Capture packets from client";
+    id = 55;
+    type = "DYNAMIC";
+    priority = 240;
+    protocol = 6;
+    primary-hash = ( "src_ip" );
+    ports = ( 5544 );
+    assignment = ( "hash" );
+    forward = ( "l2" );
+    return = ( "l2" );
+    routers = ( "10.10.50.1" );
+  },
+);

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/5f2fc30d/tools/wccp_client/wccp_client.cc
----------------------------------------------------------------------
diff --git a/tools/wccp_client/wccp_client.cc b/tools/wccp_client/wccp_client.cc
new file mode 100644
index 0000000..f8215e9
--- /dev/null
+++ b/tools/wccp_client/wccp_client.cc
@@ -0,0 +1,256 @@
+/** @file
+    WCCP cache simulation for testing.
+
+    @section license License
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ */
+
+# include <stdio.h>
+# include <unistd.h>
+# include <stdarg.h>
+# include <memory.h>
+# include <strings.h>
+# include <iostream>
+# include <iomanip>
+
+# include <getopt.h>
+
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <arpa/inet.h>
+
+# include <poll.h>
+
+# include "ink_memory.h"
+# include "Wccp.h"
+# include "WccpUtil.h"
+# include "tsconfig/TsValue.h"
+# include "ink_lockfile.h"
+
+#define WCCP_LOCK       "wccp.pid"
+
+bool do_debug = false;
+bool do_daemon = false;
+
+static char const USAGE_TEXT[] =
+  "%s\n"
+  "--address IP address to bind.\n"
+  "--router Booststrap IP address for routers.\n"
+  "--service Path to service group definitions.\n"
+  "--debug Print debugging information.\n"
+  "--daemon Run as daemon.\n"
+  "--help Print usage and exit.\n"
+  ;
+
+void Log(
+  std::ostream& out,
+  ts::Errata const& errata,
+  int indent = 0
+) {
+  for ( ts::Errata::const_iterator spot = errata.begin(), limit = errata.end();
+        spot != limit;
+        ++spot
+  ) {
+    if (spot->m_id) {
+      if (indent) out << std::setw(indent) << std::setfill(' ') << "> ";
+      out << spot->m_id << " [" << spot->m_code << "]: " << spot->m_text
+          << std::endl
+        ;
+    }
+    if (spot->getErrata().size()) Log(out, spot->getErrata(), indent+2);
+  }
+}
+
+void LogToStdErr(ts::Errata const& errata) {
+  Log(std::cerr, errata);
+}
+
+static void
+PrintErrata(ts::Errata const& err) {
+  size_t n;
+  static size_t const SIZE = 4096;
+  char buff[SIZE];
+  if (err.size()) {
+    ts::Errata::Code code = err.top().getCode();
+    if (do_debug || code >=  wccp::LVL_WARN) {
+      n = err.write(buff, SIZE, 1, 0, 2, "> ");
+      // strip trailing newlines.
+      while (n && (buff[n-1] == '\n' || buff[n-1] == '\r'))
+        buff[--n] = 0;
+      printf("%s\n", buff);
+    }
+  }
+}
+
+static void
+Init_Errata_Logging() {
+  ts::Errata::registerSink(&PrintErrata);
+}
+
+static void
+check_lockfile()
+{
+  char lockfile[256];
+  pid_t holding_pid;
+  int err;
+
+  strcpy(lockfile, "/var/run/");
+  strcat(lockfile, WCCP_LOCK);
+
+  Lockfile server_lockfile(lockfile);
+  err = server_lockfile.Get(&holding_pid);
+
+  if (err != 1) {
+    char *reason = strerror(-err);
+    fprintf(stderr, "WARNING: Can't acquire lockfile '%s'", (const char 
*)lockfile);
+
+    if ((err == 0) && (holding_pid != -1)) {
+      fprintf(stderr, " (Lock file held by process ID %ld)\n", 
(long)holding_pid);
+    } else if ((err == 0) && (holding_pid == -1)) {
+      fprintf(stderr, " (Lock file exists, but can't read process ID)\n");
+    } else if (reason) {
+      fprintf(stderr, " (%s)\n", reason);
+    } else {
+      fprintf(stderr, "\n");
+    }
+    _exit(1);
+  }
+}
+
+int
+main(int argc, char** argv) {
+  wccp::Cache wcp;
+
+
+  // getopt return values. Selected to avoid collisions with
+  // short arguments.
+  static int const OPT_ADDRESS = 257; ///< Bind to IP address option.
+  static int const OPT_HELP = 258; ///< Print help message.
+  static int const OPT_ROUTER = 259; ///< Seeded router IP address.
+  static int const OPT_SERVICE = 260; ///< Service group definition.
+  static int const OPT_DEBUG = 261; ///< Enable debug printing
+  static int const OPT_DAEMON = 262; ///< Disconnect and run as daemon
+
+  static option OPTIONS[] = {
+    { "address", 1, 0, OPT_ADDRESS },
+    { "router", 1, 0, OPT_ROUTER },
+    { "service", 1, 0, OPT_SERVICE },
+    { "debug", 0, 0, OPT_DEBUG },
+    { "daemon", 0, 0, OPT_DAEMON },
+    { "help", 0, 0, OPT_HELP },
+    { 0, 0, 0, 0 } // required terminator.
+  };
+
+  in_addr ip_addr = { INADDR_ANY };
+  in_addr router_addr = { INADDR_ANY };
+
+  int zret; // getopt return.
+  int zidx; // option index.
+  bool fail = false;
+  char const* FAIL_MSG = "";
+
+  while (-1 != (zret = getopt_long_only(argc, argv, "", OPTIONS, &zidx))) {
+    switch (zret) {
+    case OPT_HELP:
+      FAIL_MSG = "Usage:";
+      fail = true;
+      break;
+    case '?':
+      FAIL_MSG = "Invalid option specified.";
+      fail = true;
+      break;
+    case OPT_ADDRESS:
+      if (0 == inet_aton(optarg, &ip_addr)) {
+        FAIL_MSG = "Invalid IP address specified for client.";
+        fail = true;
+      }
+      break;
+    case OPT_ROUTER:
+      if (0 == inet_aton(optarg, &router_addr)) {
+        FAIL_MSG = "Invalid IP address specified for router.";
+        fail = true;
+      }
+      break;
+    case OPT_SERVICE: {
+      ts::Errata status = wcp.loadServicesFromFile(optarg);
+      if (!status) fail = true;
+      break;
+    }
+    case OPT_DEBUG: 
+      do_debug = true;
+      break;
+    case OPT_DAEMON: 
+      do_daemon = true;
+      break;
+    }
+  }
+
+  if (fail) {
+    printf(USAGE_TEXT, FAIL_MSG);
+    return 1;
+  }
+ 
+  if (0 > wcp.open(ip_addr.s_addr)) {
+    fprintf(stderr, "Failed to open or bind socket.\n");
+    return 2;
+  }
+
+  if (do_daemon) {
+    pid_t pid = fork();
+    if (pid > 0) {
+      // Successful, the parent should go away
+      _exit(0);
+    }
+  }
+
+  check_lockfile();
+
+  // Set up erratum support.
+  //ts::Errata::registerSink(&LogToStdErr);
+  Init_Errata_Logging();
+
+  static int const POLL_FD_COUNT = 1;
+  pollfd pfa[POLL_FD_COUNT];
+
+  // Poll on the socket.
+  pfa[0].fd = wcp.getSocket();
+  pfa[0].events = POLLIN;
+
+  wcp.housekeeping();
+
+  while (true) {
+    //time_t dt = std::min(wccp::TIME_UNIT, wcp.waitTime());
+    //printf("Waiting %lu milliseconds\n", dt * 1000);
+    int n = poll(pfa, POLL_FD_COUNT,  1000);
+    if (n < 0) { // error
+      perror("General polling failure");
+      return 5;
+    } else if (n > 0) { // things of interest happened
+      if (pfa[0].revents) {
+        if (pfa[0].revents & POLLIN) {
+          wcp.handleMessage();
+        } else {
+          fprintf(stderr, "Socket failure.\n");
+          return 6;
+        }
+      }
+    } else { // timeout
+      wcp.housekeeping();
+    }
+  }
+}

Reply via email to