00001 // 00002 // The SocketConnector class - establish/maintain a network connection 00003 // 00004 // ***** BEGIN LICENSE BLOCK ***** 00005 // Version: MPL 1.1/GPL 2.0/LGPL 2.1 00006 // 00007 // The contents of this file are subject to the Mozilla Public License 00008 // Version 1.1 (the "License"); you may not use this file except in 00009 // compliance with the License. You may obtain a copy of the License at 00010 // http://www.mozilla.org/MPL/ 00011 // 00012 // Software distributed under the License is distributed on an "AS IS" 00013 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 00014 // the License for the specific language governing rights and limitations 00015 // under the License. 00016 // 00017 // The Original Code is the consmgr network/serial-line monitoring package. 00018 // 00019 // The Initial Developer of the Original Code is Chris P. Ross. 00020 // Portions created by the Initial Developer are Copyright (C) 2000-2008 00021 // the Initial Developer. All Rights Reserved. 00022 // 00023 // Contributor(s): 00024 // 00025 // Alternatively, the contents of this file may be used under the terms of 00026 // either the GNU General Public License Version 2 or later (the "GPL"), or 00027 // the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 00028 // in which case the provisions of the GPL or the LGPL are applicable instead 00029 // of those above. If you wish to allow use of your version of this file only 00030 // under the terms of either the GPL or the LGPL, and not to allow others to 00031 // use your version of this file under the terms of the MPL, indicate your 00032 // decision by deleting the provisions above and replace them with the notice 00033 // and other provisions required by the GPL or the LGPL. If you do not delete 00034 // the provisions above, a recipient may use your version of this file under 00035 // the terms of any one of the MPL, the GPL or the LGPL. 00036 // 00037 // ***** END LICENSE BLOCK ***** 00038 00039 extern "C" { 00040 #include <unistd.h> 00041 #include <string.h> 00042 #include <sys/types.h> 00043 #include <sys/socket.h> 00044 #include <sys/un.h> 00045 #include <netinet/in.h> 00046 } 00047 00048 #include <sstream> 00049 00050 #include "consmgr.h" 00051 #include "guard.h" 00052 #include "sockconn.h" 00053 00054 SocketConnector::SocketConnector(SocketAddressP &addr) 00055 : FDConnector(), sock_addr(addr) 00056 { 00057 // XXX - This may not fire our sub-classes connect() method, if there 00058 // is one. This object is not fully constructed. 00059 00060 // Initiate the connection 00061 connect(); 00062 } 00063 00064 00065 // 00066 // This function actually makes the connection, blocking if need be, 00067 // only returning when complete (successfully. Throws exceptions 00068 // on failure). It is intended to be used during construction, so no 00069 // mutex locking is done. 00070 // 00071 00072 void 00073 SocketConnector::connect() 00074 { 00075 int ret, s; 00076 00077 // XXX - Should check that we're not already connected? 00078 00079 clog << "Making a new connection to " << sock_addr->get_id() << "... "; 00080 00081 /* Open a socket */ 00082 s = ::socket(sock_addr->family(), SOCK_STREAM, 0); 00083 if (s < 0) { 00084 clog << "failed!" << endl; 00085 throw(fireball(6, "socket(2) failed", true)); 00086 } 00087 00091 00092 ret = ::connect(s, (sockaddr*)sock_addr->get_addr(), sock_addr->length()); 00093 if ((ret < 0) && (errno != EINPROGRESS)) { 00094 clog << "failed!" << endl; 00095 throw(fireball(7, "connect(2) failed", true)); 00096 } 00097 00098 #ifdef SO_KEEPALIVE 00099 /* Set TCP KEEPALIVEs on this socket... */ 00100 int flags = 1; 00101 00102 if (setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (char *)&flags, 00103 sizeof(flags)) < 0) { 00104 throw(fireball(10, "setsockopt(SO_KEEPALIVE)", true)); 00105 } 00106 #endif 00107 00108 clog << "successful!" << endl; 00109 00110 // Set that we're connected, and broadcast the state change 00111 FDConnector::connect(s); 00112 } 00113 00114 // 00115 // Generate a string to tell a human who we are... 00116 // 00117 00118 std::string 00119 SocketConnector::get_id() const 00120 { 00121 std::ostringstream id_str; 00122 00123 id_str << "SocketConnector[" << sock_addr->get_id() << "]"; 00124 00125 return(id_str.str()); 00126 }