All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.caucho.server.hmux.HmuxDispatchRequest Maven / Gradle / Ivy

/*
 * Copyright (c) 1998-2018 Caucho Technology -- all rights reserved
 *
 * This file is part of Resin(R) Open Source
 *
 * Each copy or derived work must preserve the copyright notice and this
 * notice unmodified.
 *
 * Resin Open Source is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * Resin Open Source is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
 * of NON-INFRINGEMENT.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Resin Open Source; if not, write to the
 *
 *   Free Software Foundation, Inc.
 *   59 Temple Place, Suite 330
 *   Boston, MA 02111-1307  USA
 *
 * @author Scott Ferguson
 */

package com.caucho.server.hmux;

import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.caucho.VersionFactory;
import com.caucho.cloud.network.ClusterServer;
import com.caucho.cloud.topology.CloudCluster;
import com.caucho.cloud.topology.CloudPod;
import com.caucho.cloud.topology.CloudServer;
import com.caucho.server.cluster.ServletService;
import com.caucho.server.host.Host;
import com.caucho.server.host.HostController;
import com.caucho.server.webapp.WebApp;
import com.caucho.server.webapp.WebAppContainer;
import com.caucho.server.webapp.WebAppController;
import com.caucho.util.Base64;
import com.caucho.util.CharBuffer;
import com.caucho.util.Crc64;
import com.caucho.util.CurrentTime;
import com.caucho.vfs.ReadStream;
import com.caucho.vfs.WriteStream;

/**
 * Handles the filter mapping (config) requests from a remote dispatcher.
 */
public class HmuxDispatchRequest {
  private static final Logger log
    = Logger.getLogger(HmuxDispatchRequest.class.getName());

  // other, specialized protocols
  public static final int HMUX_HOST =      'h';
  public static final int HMUX_QUERY_ALL = 'q';
  public static final int HMUX_QUERY_URL = 'r';
  public static final int HMUX_QUERY_SERVER = 's';
  public static final int HMUX_WEB_APP =   'a';
  public static final int HMUX_MATCH =     'm';
  public static final int HMUX_IGNORE =    'i';
  public static final int HMUX_ETAG =      'e';
  public static final int HMUX_NO_CHANGE = 'n';
  public static final int HMUX_CLUSTER =   'c';
  public static final int HMUX_SRUN    =   's';
  public static final int HMUX_SRUN_BACKUP = 'b';
  public static final int HMUX_SRUN_SSL = 'e';
  public static final int HMUX_UNAVAILABLE = 'u';
  public static final int HMUX_WEB_APP_UNAVAILABLE = 'U';

  private CharBuffer _cb = new CharBuffer();

  private HmuxRequest _request;
  private ServletService _server;

  public HmuxDispatchRequest(HmuxRequest request)
  {
    _request = request;

    _server = request.getServer();
  }

  /**
   * Handles a new request.  Initializes the protocol handler and
   * the request streams.
   *
   * 

Note: ClientDisconnectException must be rethrown to * the caller. */ public boolean handleRequest(ReadStream is, WriteStream os) throws IOException { boolean isLoggable = log.isLoggable(Level.FINE); int code; int len; String host = ""; String etag = null; while (true) { os.flush(); code = is.read(); switch (code) { case -1: if (isLoggable) log.fine(dbgId() + "end of file"); return false; case HmuxRequest.HMUX_QUIT: if (isLoggable) log.fine(dbgId() + (char) code + ": end of request"); return true; case HmuxRequest.HMUX_EXIT: if (isLoggable) log.fine(dbgId() + (char) code + ": end of socket"); return false; case HMUX_ETAG: len = (is.read() << 8) + is.read(); _cb.clear(); is.readAll(_cb, len); etag = _cb.toString(); if (isLoggable) log.fine(dbgId() + "etag: " + etag); break; case HMUX_HOST: len = (is.read() << 8) + is.read(); _cb.clear(); is.readAll(_cb, len); host = _cb.toString(); if (isLoggable) log.fine(dbgId() + "host: " + host); break; case HMUX_QUERY_ALL: len = (is.read() << 8) + is.read(); _cb.clear(); is.readAll(_cb, len); if (isLoggable) log.fine(dbgId() + "query: " + _cb); queryAll(os, host, _cb.toString(), etag); break; /* case HMUX_QUERY_SERVER: len = (is.read() << 8) + is.read(); _cb.clear(); is.readAll(_cb, len); if (isLoggable) log.fine(dbgId() + "query-server: " + _cb); queryCluster(os, host, _cb.toString()); break; */ default: len = (is.read() << 8) + is.read(); if (isLoggable) log.fine(dbgId() + (char) code + " " + len + " (dispatch)"); is.skip(len); break; } } // _filter.setClientClosed(true); // return false; } /** * Returns the url. */ private void queryAll(WriteStream os, String hostName, String url, String etag) throws IOException { int channel = 2; boolean isLoggable = log.isLoggable(Level.FINE); os.write(HmuxRequest.HMUX_CHANNEL); os.write(channel >> 8); os.write(channel); Host host = _server.getHost(hostName, 80); if (host == null) { HostController controller = _server.getHostController(hostName, 80); if (controller != null) { writeString(os, HMUX_UNAVAILABLE, ""); } else { writeString(os, HmuxRequest.HMUX_HEADER, "check-interval"); writeString(os, HmuxRequest.HMUX_STRING, String.valueOf(_server.getDependencyCheckInterval() / 1000)); } if (isLoggable) log.fine(dbgId() + "host '" + hostName + "' not configured"); return; } else if (! host.getState().isActive()) { writeString(os, HMUX_UNAVAILABLE, ""); if (isLoggable) log.fine(dbgId() + "host '" + host + "' not active"); return; } if (host.getConfigETag() == null) sendQuery(null, host, hostName, url); if (etag == null) { } else if (etag.equals(host.getConfigETag())) { if (isLoggable) log.fine(dbgId() + "host '" + host + "' no change"); writeString(os, HMUX_NO_CHANGE, ""); return; } else if (etag.equals("h-" + host.getName())) { if (isLoggable) { log.fine(dbgId() + "host alias '" + hostName + " -> '" + host + "' no change"); } writeString(os, HMUX_NO_CHANGE, ""); return; } else { if (isLoggable) log.fine(dbgId() + "host '" + host + "' changed"); } sendQuery(os, host, hostName, url); } /** * Writes the host data, returning the crc */ private void sendQuery(WriteStream os, Host host, String hostName, String url) throws IOException { boolean isLoggable = log.isLoggable(Level.FINE); long crc64 = 0; if (! CurrentTime.isTest()) crc64 = Crc64.generate(crc64, VersionFactory.getFullVersion()); queryServer(os); String canonicalHostName = host.getHostName(); if (canonicalHostName.equals("default")) canonicalHostName = ""; writeString(os, HMUX_HOST, canonicalHostName); if (hostName.equals(canonicalHostName)) { crc64 = queryCluster(os, host, crc64); WebAppContainer webAppContainer = host.getWebAppContainer(); WebAppController controller = webAppContainer.findByURI(url); if (controller != null) { try { controller.request(); } catch (Throwable e) { log.log(Level.WARNING, e.toString(), e); } } for (WebAppController appEntry : webAppContainer.getWebAppList()) { if (appEntry.getParent() != null && appEntry.getParent().isDynamicDeploy()) { continue; } writeString(os, HMUX_WEB_APP, appEntry.getContextPath()); if (isLoggable) log.fine(dbgId() + "web-app '" + appEntry.getContextPath() + "'"); crc64 = Crc64.generate(crc64, appEntry.getContextPath()); WebApp app = appEntry.getWebApp(); if (appEntry.isDynamicDeploy()) { writeString(os, HMUX_MATCH, "/*"); crc64 = Crc64.generate(crc64, "/*"); if (isLoggable) log.fine(dbgId() + "dynamic '" + appEntry.getContextPath() + "'"); } else if (app == null || ! app.isActive()) { if (isLoggable) log.fine(dbgId() + "not active '" + appEntry.getContextPath() + "'"); writeString(os, HMUX_WEB_APP_UNAVAILABLE, ""); } else { if (isLoggable) log.fine(dbgId() + "active '" + appEntry.getContextPath() + "'"); ArrayList patternList = app.getServletMappingPatterns(); for (int j = 0; patternList != null && j < patternList.size(); j++) { String pattern = patternList.get(j); writeString(os, HMUX_MATCH, pattern); crc64 = Crc64.generate(crc64, pattern); } patternList = app.getServletIgnoreMappingPatterns(); for (int j = 0; patternList != null && j < patternList.size(); j++) { String pattern = patternList.get(j); writeString(os, HMUX_IGNORE, pattern); crc64 = Crc64.generate(crc64, "i"); crc64 = Crc64.generate(crc64, pattern); } } } CharBuffer cb = new CharBuffer(); Base64.encode(cb, crc64); String newETag = cb.close(); host.setConfigETag(newETag); writeString(os, HMUX_ETAG, host.getConfigETag()); } else { // aliased hosts use the host name as the etag writeString(os, HMUX_ETAG, "h-" + host.getName()); } } /** * Queries the cluster. */ private long queryCluster(WriteStream os, Host host, long crc64) throws IOException { /* int channel = 2; os.write(HmuxRequest.HMUX_CHANNEL); os.write(channel >> 8); os.write(channel); */ CloudCluster cluster = host.getCluster(); if (cluster == null) return 0; writeString(os, HMUX_CLUSTER, cluster.getId()); crc64 = Crc64.generate(crc64, cluster.getId()); CloudPod []pods = cluster.getPodList(); int serverLength = (pods.length > 0 ? pods[0].getServerLength() : 0); CloudServer []servers = (pods.length > 0 ? pods[0].getServerList() : null); if (serverLength > 0) { CloudServer cloudServer = servers[0]; ClusterServer server = cloudServer.getData(ClusterServer.class); crc64 = writeTime(os, crc64, "live-time", server.getLoadBalanceIdleTime()); crc64 = writeTime(os, crc64, "dead-time", server.getLoadBalanceRecoverTime()); crc64 = writeTime(os, crc64, "read-timeout", server.getLoadBalanceSocketTimeout()); crc64 = writeTime(os, crc64, "connect-timeout", server.getLoadBalanceConnectTimeout()); } for (int i = 0; i < serverLength; i++) { CloudServer cloudServer = servers[i]; if (cloudServer == null) continue; ClusterServer server = cloudServer.getData(ClusterServer.class); if (server != null) { String srunHost = server.getIp() + ":" + server.getPort(); boolean isSSL = false; // server.isSSL(); if (server.isBackup()) writeString(os, HMUX_SRUN_BACKUP, srunHost); else if (isSSL) writeString(os, HMUX_SRUN_SSL, srunHost); else writeString(os, HMUX_SRUN, srunHost); crc64 = Crc64.generate(crc64, srunHost); } } return crc64; } private long writeTime(WriteStream os, long crc, String header, long time) throws IOException { crc = Crc64.generate(crc, time); writeTime(os, header, time); return crc; } private void writeTime(WriteStream os, String header, long time) throws IOException { writeString(os, HmuxRequest.HMUX_HEADER, header); writeString(os, HmuxRequest.HMUX_STRING, "" + ((time + 999) / 1000)); } /** * Queries the cluster. */ private void queryServer(WriteStream os) throws IOException { writeTime(os, "check-interval", _server.getDependencyCheckInterval()); writeString(os, HmuxRequest.HMUX_HEADER, "cookie"); writeString(os, HmuxRequest.HMUX_STRING, _server.getSessionCookie()); writeString(os, HmuxRequest.HMUX_HEADER, "ssl-cookie"); writeString(os, HmuxRequest.HMUX_STRING, _server.getSSLSessionCookie()); writeString(os, HmuxRequest.HMUX_HEADER, "session-url-prefix"); writeString(os, HmuxRequest.HMUX_STRING, _server.getSessionURLPrefix()); writeString(os, HmuxRequest.HMUX_HEADER, "alt-session-url-prefix"); writeString(os, HmuxRequest.HMUX_STRING, _server.getAlternateSessionURLPrefix()); if (_server.getConnectionErrorPage() != null) { writeString(os, HmuxRequest.HMUX_HEADER, "connection-error-page"); writeString(os, HmuxRequest.HMUX_STRING, _server.getConnectionErrorPage()); } } void writeString(WriteStream os, int code, String value) throws IOException { if (os == null) return; if (value == null) value = ""; int len = value.length(); os.write(code); os.write(len >> 8); os.write(len); os.print(value); if (log.isLoggable(Level.FINE)) log.fine(dbgId() + (char)code + " " + value); } void writeString(WriteStream os, int code, CharBuffer value) throws IOException { if (os == null) return; int len = value.length(); os.write(code); os.write(len >> 8); os.write(len); os.print(value); if (log.isLoggable(Level.FINE)) log.fine(dbgId() + (char)code + " " + value); } private String dbgId() { return _request.dbgId(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy