From mboxrd@z Thu Jan 1 00:00:00 1970 From: rmccabe@sourceware.org Date: 27 Mar 2007 02:06:31 -0000 Subject: [Cluster-devel] conga/ricci common/ClientSocket.cpp common/Mak ... Message-ID: <20070327020631.8786.qmail@sourceware.org> List-Id: To: cluster-devel.redhat.com MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit CVSROOT: /cvs/cluster Module name: conga Branch: RHEL4 Changes by: rmccabe at sourceware.org 2007-03-27 03:06:28 Modified files: ricci/common : ClientSocket.cpp Makefile Socket.cpp Time.cpp XML.cpp ricci/include : Socket.h ricci/modules/cluster/clumon/src/daemon: Monitor.cpp Monitor.h ricci/ricci : Ricci.cpp Added files: ricci/common : Network.cpp ricci/include : Network.h ricci/test_suite: SSLClient_send_to_ricci Log message: - Fix a bug that could caused blocking connections under some circumstances. - Include a new test script that uses the conga SSL python module. - Upgrade to Zope 2.8.9. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/common/Network.cpp.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=NONE&r2=1.1.2.1 http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/common/ClientSocket.cpp.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=1.4&r2=1.4.4.1 http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/common/Makefile.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=1.7&r2=1.7.2.1 http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/common/Socket.cpp.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=1.3&r2=1.3.4.1 http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/common/Time.cpp.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=1.4&r2=1.4.4.1 http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/common/XML.cpp.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=1.7&r2=1.7.2.1 http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/include/Network.h.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=NONE&r2=1.1.2.1 http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/include/Socket.h.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=1.3&r2=1.3.4.1 http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/cluster/clumon/src/daemon/Monitor.cpp.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=1.13&r2=1.13.2.1 http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/cluster/clumon/src/daemon/Monitor.h.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=1.5&r2=1.5.4.1 http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/ricci/Ricci.cpp.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=1.22&r2=1.22.2.1 http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/test_suite/SSLClient_send_to_ricci.diff?cvsroot=cluster&only_with_tag=RHEL4&r1=NONE&r2=1.1.2.1 /cvs/cluster/conga/ricci/common/Network.cpp,v --> standard output revision 1.1.2.1 --- conga/ricci/common/Network.cpp +++ - 2007-03-27 03:06:29.628153000 +0100 @@ -0,0 +1,84 @@ +/* + Copyright Red Hat, Inc. 2007 + + This program 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, or (at your option) any + later version. + + This program 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. 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; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 675 Mass Ave, Cambridge, + MA 02139, USA. +*/ +/* + * Author: Stanko Kupcevic + */ + + +#include "Network.h" + +#include +#include +#include + + + +counting_auto_ptr +Network::getHostByName(const String& hostname) +{ + counting_auto_ptr ent_d(new Hostent()); + struct hostent *ent = 0; + int error; + gethostbyname2_r(hostname.c_str(), AF_INET, + &(ent_d->ent), + ent_d->data, sizeof(ent_d->data), + &ent, + &error); + if (ent == &(ent_d->ent)) + return ent_d; + throw String("unable to resolve ") + hostname; +} + + +std::vector +Network::name2IP(const String& hostname) +{ + std::vector addrs; + try { + char buff[INET_ADDRSTRLEN+1]; + counting_auto_ptr hent = getHostByName(hostname); + char** addrs_b = (*hent)->h_addr_list; + for (int i=0; addrs_b[i]; i++) { + struct in_addr addr; + addr.s_addr = *((u_int32_t*) addrs_b[i]); + if (inet_ntop(AF_INET, &addr, buff, sizeof(buff))) + addrs.push_back(buff); + } + } catch ( ... ) {} + return addrs; +} + + +String +Network::localhost() +{ + // get hostname + char name[1024]; + if (gethostname(name, sizeof(name)-1)) + return ""; + name[sizeof(name)-1] = '\0'; + + try { + // get fqdn + counting_auto_ptr ent = getHostByName(name); + return String((*ent)->h_name); + } catch ( ... ) { + return name; + } +} --- conga/ricci/common/ClientSocket.cpp 2006/08/10 22:53:07 1.4 +++ conga/ricci/common/ClientSocket.cpp 2007/03/27 02:06:26 1.4.4.1 @@ -1,5 +1,5 @@ /* - Copyright Red Hat, Inc. 2005 + Copyright Red Hat, Inc. 2005-2007 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -23,6 +23,7 @@ #include "Socket.h" #include "Logger.h" +#include "Network.h" #include #include @@ -38,7 +39,7 @@ Socket(-1) {} -ClientSocket::ClientSocket(int sock, unsigned int addr) : +ClientSocket::ClientSocket(int sock, u_int32_t addr) : Socket(sock), _addr(addr) {} @@ -66,34 +67,57 @@ // log(msg, LogSocket); } -ClientSocket::ClientSocket(const String& hostname, unsigned short port) : +ClientSocket::ClientSocket(const String& hostname, + unsigned short port, + unsigned int timeout_ms) : Socket(-1) { _sock = socket(PF_INET, SOCK_STREAM, 0); if (_sock == -1) - throw String("ClientSocket(hostname, port): socket() failed"); + throw String("ClientSocket(hostname, port, timeout): socket() failed"); - struct hostent* ent = gethostbyname2(hostname.c_str(), AF_INET); - if (!ent) - throw String("ClientSocket(hostname, port): gethostbyname() failed"); + if (timeout_ms) + nonblocking(true); - char** addrs = ent->h_addr_list; + counting_auto_ptr ent = Network::getHostByName(hostname); + + char** addrs = (*ent)->h_addr_list; for (int i=0; addrs[i]; i++) { struct sockaddr_in addr_in; addr_in.sin_family = AF_INET; addr_in.sin_port = htons(port); addr_in.sin_addr.s_addr = *((u_int32_t*) addrs[i]); - if (connect(_sock, (struct sockaddr*) &addr_in, sizeof(addr_in))) - continue; - else { - // String msg = String("created client socket ") + _sock; - // msg += ", and connected to " + hostname + ", port " + port; - // log(msg, LogSocket); + + if (connect(_sock, (struct sockaddr*) &addr_in, sizeof(addr_in)) == 0) { + // connected + nonblocking(false); _addr = addr_in.sin_addr.s_addr; return; } + + // connect() error + if (errno != EINPROGRESS) + continue; + bool can_read=false, can_write=true; + poll(can_read, can_write, timeout_ms); + if (can_write == false) { + // connect() not completed + throw String("ClientSocket(hostname, port, timeout): connect() timed out"); + } + // connect() completed, check successfulness + int err = 1; + socklen_t err_size = sizeof(err); + getsockopt(_sock, SOL_SOCKET, SO_ERROR, + &err, &err_size); + if (err) + continue; + + // connected + nonblocking(false); + _addr = addr_in.sin_addr.s_addr; + return; } - throw String("ClientSocket(hostname, port): connect() failed"); + throw String("ClientSocket(hostname, port, timeout): connect() failed"); } ClientSocket::ClientSocket(const ClientSocket& s) : @@ -118,14 +142,13 @@ bool ClientSocket::connected_to(const String& hostname) { - struct hostent* ent = gethostbyname2(hostname.c_str(), AF_INET); - if (!ent) - return false; - - char** addrs = ent->h_addr_list; - for (int i=0; addrs[i]; i++) - if (*((u_int32_t*) addrs[i]) == _addr) - return true; + try { + counting_auto_ptr ent = Network::getHostByName(hostname); + char** addrs = (*ent)->h_addr_list; + for (int i=0; addrs[i]; i++) + if (*((u_int32_t*) addrs[i]) == _addr) + return true; + } catch ( ... ) {} return false; } @@ -153,10 +176,23 @@ // log(String("received ") + ret + " bytes from socket " + _sock, // LogLevel(LogSocket|LogTransfer)); - return String(buffer, ret); + String data(buffer, ret); + shred(buffer, ret); + return data; } } +String +ClientSocket::recv(int timeout) +{ + bool in=true, out=false; + poll(in, out, timeout); + if (in) + return recv(); + else + return ""; +} + String ClientSocket::send(const String& msg) { @@ -171,7 +207,7 @@ else if (errno == EAGAIN || errno == EWOULDBLOCK) return msg; - throw String("ClientSocket::recv(): socket error"); + throw String("ClientSocket::send(): socket error"); } // log(String("sent ") + ret + " bytes thru socket " + _sock, @@ -180,6 +216,17 @@ } } +String +ClientSocket::send(const String& msg, int timeout) +{ + bool in=false, out=true; + poll(in, out, timeout); + if (out) + return send(msg); + else + return msg; +} + void ClientSocket::ready(bool& recv, bool& send, int timeout) { --- conga/ricci/common/Makefile 2006/10/23 18:43:35 1.7 +++ conga/ricci/common/Makefile 2007/03/27 02:06:26 1.7.2.1 @@ -24,10 +24,11 @@ utils.o \ File.o \ XML.o \ + Network.o \ Socket.o \ ServerSocket.o \ - Logger.o \ ClientSocket.o \ + Logger.o \ Variable.o \ Random.o \ daemon_init.o \ --- conga/ricci/common/Socket.cpp 2006/08/10 22:53:07 1.3 +++ conga/ricci/common/Socket.cpp 2007/03/27 02:06:26 1.3.4.1 @@ -1,5 +1,5 @@ /* - Copyright Red Hat, Inc. 2005 + Copyright Red Hat, Inc. 2005-2007 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -181,23 +181,3 @@ } } } - - - -std::vector -name2IP(const String& hostname) -{ - char buff[INET_ADDRSTRLEN+1]; - std::vector addrs; - struct hostent* ent = gethostbyname2(hostname.c_str(), AF_INET); - if (!ent) - return addrs; - char** addrs_b = ent->h_addr_list; - for (int i=0; addrs_b[i]; i++) { - struct in_addr addr; - addr.s_addr = *((u_int32_t*) addrs_b[i]); - if (inet_ntop(AF_INET, &addr, buff, sizeof(buff))) - addrs.push_back(buff); - } - return addrs; -} --- conga/ricci/common/Time.cpp 2006/08/10 22:53:07 1.4 +++ conga/ricci/common/Time.cpp 2007/03/27 02:06:26 1.4.4.1 @@ -1,5 +1,5 @@ /* - Copyright Red Hat, Inc. 2005 + Copyright Red Hat, Inc. 2005-2007 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -31,8 +31,7 @@ time_sec() { struct timeval t; - struct timezone z; - gettimeofday(&t, &z); + gettimeofday(&t, NULL); return t.tv_sec; } @@ -40,8 +39,7 @@ time_mil() { struct timeval t; - struct timezone z; - gettimeofday(&t, &z); + gettimeofday(&t, NULL); return t.tv_sec*1000 + t.tv_usec/1000; } --- conga/ricci/common/XML.cpp 2006/10/23 18:43:35 1.7 +++ conga/ricci/common/XML.cpp 2007/03/27 02:06:26 1.7.2.1 @@ -189,7 +189,7 @@ xml.size(), "noname.xml", NULL, - XML_PARSE_NONET); + XML_PARSE_NONET | XML_PARSE_NOERROR | XML_PARSE_NOWARNING); if (!doc) throw String("parseXML(): couldn't parse xml"); @@ -216,7 +216,7 @@ xml.size(), "noname.xml", NULL, - XML_PARSE_NONET); + XML_PARSE_NONET | XML_PARSE_NOERROR | XML_PARSE_NOWARNING); if (!doc) { // cout << xml << endl; throw String("generateXML(): internal error"); /cvs/cluster/conga/ricci/include/Network.h,v --> standard output revision 1.1.2.1 --- conga/ricci/include/Network.h +++ - 2007-03-27 03:06:30.380086000 +0100 @@ -0,0 +1,54 @@ +/* + Copyright Red Hat, Inc. 2007 + + This program 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, or (at your option) any + later version. + + This program 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. 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; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 675 Mass Ave, Cambridge, + MA 02139, USA. +*/ +/* + * Author: Stanko Kupcevic + */ + + +#ifndef Conga_Network_h +#define Conga_Network_h + +#include "counting_auto_ptr.h" +#include "String.h" +#include + +#include + + +class Network +{ + public: + static std::vector name2IP(const String& hostname); + static String localhost(); + + + class Hostent + { + public: + struct hostent ent; + char data[4*1024 - sizeof(struct hostent)]; + struct hostent* operator->() { return &ent; } + struct hostent& operator*() { return ent; } + }; + static counting_auto_ptr getHostByName(const String& hostname); + +}; + + +#endif // Conga_Network_h --- conga/ricci/include/Socket.h 2006/08/10 22:53:07 1.3 +++ conga/ricci/include/Socket.h 2007/03/27 02:06:27 1.3.4.1 @@ -34,14 +34,11 @@ // provide external locking -std::vector name2IP(const String& hostname); - - class Socket { public: Socket(const Socket&); - Socket& operator= (const Socket&); + virtual Socket& operator= (const Socket&); virtual ~Socket(); virtual bool operator== (const Socket&); @@ -73,24 +70,29 @@ public: ClientSocket(); ClientSocket(const String& sock_path); // UNIX socket - ClientSocket(const String& hostname, unsigned short port); // TCP socket + ClientSocket(const String& hostname, unsigned short port, + unsigned int timeout_ms=0 /* 0 - standard blocking behavior + >0 - timeout + */ ); // TCP socket ClientSocket(const ClientSocket&); - ClientSocket& operator= (const ClientSocket&); + virtual ClientSocket& operator= (const ClientSocket&); virtual ~ClientSocket(); - String recv(); - String send(const String& msg); // return what is left to send + virtual String recv(); + virtual String recv(int timeout); + virtual String send(const String& msg); // return what is left to send + virtual String send(const String& msg, int timeout); - void ready(bool& recv, bool& send, int timeout); + virtual void ready(bool& recv, bool& send, int timeout); virtual bool server() { return false; } virtual bool connected_to(const String& hostname); protected: - unsigned int _addr; + u_int32_t _addr; // address in network byte order - ClientSocket(int sock, unsigned int addr=0); // takes ownership of sock + ClientSocket(int sock, u_int32_t addr=0); // takes ownership of sock friend class ServerSocket; }; // ClientSocket @@ -101,12 +103,12 @@ ServerSocket(const String& sock_path); // UNIX socket ServerSocket(unsigned short port); // TCP socket ServerSocket(const ServerSocket&); - ServerSocket& operator= (const ServerSocket&); + virtual ServerSocket& operator= (const ServerSocket&); virtual ~ServerSocket(); ClientSocket accept(); - bool ready(int timeout); + virtual bool ready(int timeout); virtual bool server() { return true; } --- conga/ricci/modules/cluster/clumon/src/daemon/Monitor.cpp 2006/12/13 19:14:54 1.13 +++ conga/ricci/modules/cluster/clumon/src/daemon/Monitor.cpp 2007/03/27 02:06:27 1.13.2.1 @@ -26,6 +26,7 @@ #include "Logger.h" #include "Time.h" #include "utils.h" +#include "Network.h" #include #include @@ -584,7 +585,7 @@ iter != nodenames.end(); iter++) { const String& nodename = *iter; - vector ips = name2IP(nodename); + vector ips = Network::name2IP(nodename); for (vector::iterator iter_ip = ips.begin(); iter_ip != ips.end(); iter_ip++) { --- conga/ricci/modules/cluster/clumon/src/daemon/Monitor.h 2006/10/13 09:36:16 1.5 +++ conga/ricci/modules/cluster/clumon/src/daemon/Monitor.h 2007/03/27 02:06:27 1.5.4.1 @@ -49,7 +49,7 @@ const String& msg); protected: - void run(); + virtual void run(); private: Mutex _mutex; // _cluster and _cache --- conga/ricci/ricci/Ricci.cpp 2007/01/04 00:19:49 1.22 +++ conga/ricci/ricci/Ricci.cpp 2007/03/27 02:06:27 1.22.2.1 @@ -31,13 +31,13 @@ #include "Time.h" #include "XML_tags.h" #include "File.h" +#include "Network.h" #include #include #include #include #include -#include #include @@ -45,7 +45,6 @@ static bool dom0(); -static String hostname(); static pair clusterinfo(); static String os_release(); @@ -71,7 +70,7 @@ header.set_attr("authenticated", "false"); if (full) { - String name = hostname(); + String name = Network::localhost(); if (name.size()) header.set_attr("hostname", name); @@ -459,20 +458,6 @@ - -String -hostname() -{ - char name[1024]; - if (gethostname(name, sizeof(name))) - return ""; - struct hostent *ent = gethostbyname(name); - if (ent) - return String(ent->h_name); - else - return name; -} - pair clusterinfo() { /cvs/cluster/conga/ricci/test_suite/SSLClient_send_to_ricci,v --> standard output revision 1.1.2.1 --- conga/ricci/test_suite/SSLClient_send_to_ricci +++ - 2007-03-27 03:06:31.087013000 +0100 @@ -0,0 +1,70 @@ +#!/usr/bin/python + +import socket +import sys, os +import xml.dom +import xml +from xml.dom import minidom + +import sys +sys.path.append('/var/lib/luci/Extensions') +from conga_ssl import SSLSocket + + +WRITE_TIMEOUT = 600 +READ_TIMEOUT = 600 +CONNECT_TIMEOUT = 4 + +RICCI_PORT = 11111 + + +def send_to_ricci(hostname, msg): + ss = SSLSocket(hostname, RICCI_PORT, CONNECT_TIMEOUT) + + res1 = ss.recv(READ_TIMEOUT) + ss.send(msg, WRITE_TIMEOUT) + res2 = '' + while True: + buff = ss.recv(READ_TIMEOUT) + if buff == '': + break + res2 += buff + try: + minidom.parseString(res2) + break + except: + pass + return res1, res2 + + +def main(argv): + certs_present = True + if os.access('cacert.pem', os.R_OK) == False: + print 'cannot find cacert.pem' + certs_present = False + if os.access('privkey.pem', os.R_OK) == False: + print 'cannot find privkey.pem' + certs_present = False + + if len(argv) != 3 or not certs_present: + print 'sends to ricci on , and writes its response to stdout' + print '\t' + argv[0] + ' ' + print '\t\thostname - host to send command to' + print '\t\txml_file - file with valid ricci request to be sent' + print '\t./ has to contain privkey.pem and cacert.pem' + sys.exit(1) + + hostname = argv[1] + filename = argv[2] + res = send_to_ricci(hostname, open(filename).read(100000)) + print res[1] + if res[1].find('success="5"') > -1: + print "not authenticated, send ricci/authenticate.xml with root password in it" + + + + +# If called from the command line +if __name__ == '__main__': + main(sys.argv) +