00001 // 00002 // The UDSListener class - establish/maintain a connection via a UNIX Domain Socket 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 <sys/stat.h> 00042 #include <sys/socket.h> 00043 #include <sys/un.h> 00044 } 00045 00046 #include <sstream> 00047 00048 #include "consmgr.h" 00049 #include "udslistener.h" 00050 #include "guard.h" 00051 00052 UDSListener::UDSListener(SocketAddressP &path) 00053 : SocketListener(path) 00054 { 00055 } 00056 00057 UDSListener::~UDSListener() 00058 { 00059 // Call disconnect to do any cleanup/closedown. 00060 disconnect(); 00061 } 00062 00063 00067 void 00068 UDSListener::disconnect() 00069 { 00070 SocketListener::disconnect(); 00071 00072 // Lock the mutex before accessing methods in sock_addr 00073 // XXX Is this really necessary? I doubt it; the address is const and 00074 // immutable. What could happen? 00075 Guard locker(&mutex); 00076 00077 // Delete the socket file; no one can connect to it anymore if we're 00078 // no longer listening! 00079 reinterpret_cast<const UDSSocketAddress&>(*sock_addr).unlink(); 00080 } 00081 00085 int 00086 UDSListener::make_incoming_socket() 00087 { 00088 clog << "In UDSListener::make_incoming_socket()" << endl; 00089 00090 // Create a new scope for the Guard, so that we release the mutex before 00091 // we call SocketListener::make_incoming_socket, which will lock it again. 00092 // However, this seems problematic; shouldn't we keep the mutex locked for 00093 // this entire operation? But see the note in 00094 // SocketListener::make_incoming_socket; this needs work, anyway. 00095 { 00096 struct stat statbuf; 00097 sockaddr_un *addr_un; 00098 Guard locker(&mutex); 00099 00100 addr_un = (sockaddr_un *)sock_addr->get_addr(); 00101 00102 // Now I need to check to make sure the UDS wasn't created earlier. 00103 // Perhaps I should catch this error, but for now just nuking it seems 00104 // an acceptable action... 00105 if ((stat(addr_un->sun_path, &statbuf) >= 0) && 00106 (S_ISSOCK(statbuf.st_mode))) { 00107 clog << "Auto-nuking \"" << addr_un->sun_path << "\"..." << endl; 00108 unlink(addr_un->sun_path); 00109 } else { 00110 // XXX - While I'm here, I should catch if it's *not* a socket 00111 // file, perhaps if it's a file, directory, etc... 00112 clog << "Hrm, the UDS path '" << addr_un->sun_path << "' exists, " 00113 << "but is not a socket. Its st_mode is " << statbuf.st_mode 00114 << endl; 00115 } 00116 } 00117 00118 // Okay, now do the rest of the work 00119 return SocketListener::make_incoming_socket(); 00120 } 00121 00122 // 00123 // Generate a string to tell a human who we are... 00124 // 00125 00126 std::string 00127 UDSListener::get_id() const 00128 { 00129 std::ostringstream id_str; 00130 00131 id_str << "UDSListener[" << sock_addr->get_id() << "]"; 00132 00133 return(id_str.str()); 00134 }