/**************************************************************************/ /* */ /* Copyright (c) 2015 Qindel Formacion y Servicios SL. */ /* */ /* This program is free software; you can redistribute it and/or modify */ /* it under the terms of the GNU General Public License Version 2, as */ /* published by the Free Software Foundation. */ /* */ /* This program is distributed in the hope that it will be useful, but */ /* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTA- */ /* BILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General */ /* Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, you can request a copy to Qindel */ /* or write to the Free Software Foundation, Inc., 59 Temple Place, Suite */ /* 330, Boston, MA 02111-1307 USA */ /* */ /* All rights reserved. */ /* */ /**************************************************************************/ #include #include #include #include #include "ChannelEndPoint.h" #include "NXalert.h" ChannelEndPoint::ChannelEndPoint(const char *spec) : defaultTCPPort_(0), defaultTCPInterface_(0), defaultUnixPath_(NULL) { spec_ = (spec ? strdup(spec) : NULL); } void ChannelEndPoint::setSpec(const char *spec) { if (spec_) free(spec_); if (spec && strlen(spec)) spec_ = strdup(spec); else spec_ = NULL; } void ChannelEndPoint::setSpec(int port) { if (port >= 0) { char tmp[20]; sprintf(tmp, "%d", port); setSpec(tmp); } else setSpec((char*)NULL); } void ChannelEndPoint::setDefaultTCPPort(long port) { defaultTCPPort_ = port; } void ChannelEndPoint::setDefaultTCPInterface(int publicInterface) { defaultTCPInterface_ = publicInterface; } void ChannelEndPoint::setDefaultUnixPath(char *path) { if (defaultUnixPath_) free(defaultUnixPath_); if (path && strlen(path)) defaultUnixPath_ = strdup(path); else defaultUnixPath_ = NULL; } void ChannelEndPoint::disable() { setSpec("0"); } bool ChannelEndPoint::specIsPort(long *port) const { if (port) *port = 0; long p = -1; if (spec_) { char *end; p = strtol(spec_, &end, 10); if ((end == spec_) || (*end != '\0')) return false; } if (port) *port = p; return true; } bool ChannelEndPoint::getUnixPath(char **unixPath) const { if (unixPath) *unixPath = 0; long p; char *path = NULL; if (specIsPort(&p)) { if (p != 1) return false; } else if (spec_ && (strncmp("unix:", spec_, 5) == 0)) { path = spec_ + 5; } else return false; if (!path || (*path == '\0')) { path = defaultUnixPath_; if (!path) return false; } if (unixPath) *unixPath = strdup(path); return true; } // FIXME!!! static const char * getComputerName() { // // Strangely enough, under some Windows OSes SMB // service doesn't bind to localhost. Fall back // to localhost if can't find computer name in // the environment. In future we should try to // bind to localhost and then try the other IPs. // const char *hostname = NULL; #ifdef __CYGWIN32__ hostname = getenv("COMPUTERNAME"); #endif if (hostname == NULL) { hostname = "localhost"; } return hostname; } bool ChannelEndPoint::getTCPHostAndPort(char **host, long *port) const { long p; char *h = NULL; ssize_t h_len; if (host) *host = NULL; if (port) *port = 0; if (specIsPort(&p)) { h_len = 0; } else if (spec_ && (strncmp("tcp:", spec_, 4) == 0)) { h = spec_ + 4; char *colon = strrchr(h, ':'); if (colon) { char *end; h_len = colon++ - h; p = strtol(colon, &end, 10); if ((end == colon) || (*end != '\0')) return false; } else { h_len = strlen(h); p = 1; } } else return false; if (p == 1) p = defaultTCPPort_; if (p < 1) return false; if (port) *port = p; if (host) *host = ( h_len ? strndup(h, h_len) : strdup(defaultTCPInterface_ ? getComputerName() : "localhost")); return true; } bool ChannelEndPoint::enabled() const { return (getUnixPath() || getTCPHostAndPort()); } long ChannelEndPoint::getTCPPort() const { long port; if (getTCPHostAndPort(NULL, &port)) return port; return -1; } bool ChannelEndPoint::validateSpec() { return (specIsPort() || getUnixPath() || getTCPHostAndPort()); } ChannelEndPoint &ChannelEndPoint::operator=(const ChannelEndPoint &other) { char *old; defaultTCPPort_ = other.defaultTCPPort_; defaultTCPInterface_ = other.defaultTCPInterface_; old = defaultUnixPath_; defaultUnixPath_ = (other.defaultUnixPath_ ? strdup(other.defaultUnixPath_) : NULL); free(old); old = spec_; spec_ = (other.spec_ ? strdup(other.spec_) : NULL); free(old); return *this; } std::ostream& operator<<(std::ostream& os, const ChannelEndPoint& endPoint) { if (endPoint.enabled()) { char *unixPath, *host; long port; if (endPoint.getUnixPath(&unixPath)) { os << "unix:" << unixPath; free(unixPath); } else if (endPoint.getTCPHostAndPort(&host, &port)) { os << "tcp:" << host << ":" << port; free(host); } else { os << "(invalid)"; } } else { os << "(disabled)"; } return os; }