00001 /****************** <VPR heading BEGIN do not edit this line> ***************** 00002 * 00003 * VR Juggler Portable Runtime 00004 * 00005 * Original Authors: 00006 * Allen Bierbaum, Patrick Hartling, Kevin Meinert, Carolina Cruz-Neira 00007 * 00008 * ----------------------------------------------------------------- 00009 * File: $RCSfile$ 00010 * Date modified: $Date: 2005-01-17 22:34:01 -0600 (Mon, 17 Jan 2005) $ 00011 * Version: $Revision: 16635 $ 00012 * ----------------------------------------------------------------- 00013 * 00014 ****************** <VPR heading END do not edit this line> ******************/ 00015 00016 /*************** <auto-copyright.pl BEGIN do not edit this line> ************** 00017 * 00018 * VR Juggler is (C) Copyright 1998-2005 by Iowa State University 00019 * 00020 * Original Authors: 00021 * Allen Bierbaum, Christopher Just, 00022 * Patrick Hartling, Kevin Meinert, 00023 * Carolina Cruz-Neira, Albert Baker 00024 * 00025 * This library is free software; you can redistribute it and/or 00026 * modify it under the terms of the GNU Library General Public 00027 * License as published by the Free Software Foundation; either 00028 * version 2 of the License, or (at your option) any later version. 00029 * 00030 * This library is distributed in the hope that it will be useful, 00031 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00032 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00033 * Library General Public License for more details. 00034 * 00035 * You should have received a copy of the GNU Library General Public 00036 * License along with this library; if not, write to the 00037 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00038 * Boston, MA 02111-1307, USA. 00039 * 00040 *************** <auto-copyright.pl END do not edit this line> ***************/ 00041 00042 #include <vpr/vprConfig.h> 00043 #include <vpr/IO/Selector.h> 00044 #include <vpr/Util/Assert.h> 00045 #include <vpr/Util/Debug.h> 00046 #include <vpr/IO/Socket/SocketConnector.h> 00047 00048 00049 namespace vpr 00050 { 00051 00052 vpr::ReturnStatus SocketConnector::connect(vpr::SocketStream& newStream, 00053 const vpr::InetAddr& remoteAddr, 00054 vpr::Interval timeout, 00055 const vpr::InetAddr& localAddr) 00056 { 00057 vpr::ReturnStatus ret_val; 00058 //vpr::InetAddr remote_addr; 00059 00060 // Open the socket 00061 if(!checkOpen(newStream)) 00062 { 00063 return vpr::ReturnStatus(vpr::ReturnStatus::Fail); 00064 } 00065 00066 /* This actually happens in connect start 00067 if ( localAddr != vpr::InetAddr::AnyAddr ) 00068 { 00069 vpr::ReturnStatus status; 00070 newStream.setLocalAddr(localAddr); 00071 status = newStream.bind(); 00072 vprASSERT(status.success() && "Failed to bind local address"); 00073 } 00074 */ 00075 00076 // Start the connection 00077 if(!connectStart(newStream, timeout, localAddr)) 00078 { 00079 return vpr::ReturnStatus(vpr::ReturnStatus::Fail); 00080 } 00081 00082 newStream.setRemoteAddr(remoteAddr); 00083 00084 // Attempt the connection 00085 ret_val = newStream.connect(timeout); 00086 00087 /* 00088 // If the connect call did not return success, it may be the result of 00089 // using non-blocking sockets. 00090 if ( ! ret_val.success() ) 00091 { 00092 // If connect() gave us a status saying that the connection is in 00093 // progress, try to complete the connection after the timeout period. 00094 // If there is no timeout period, simply return immediately. 00095 if ( ret_val == vpr::ReturnStatus::InProgress || 00096 ret_val == vpr::ReturnStatus::WouldBlock ) 00097 { 00098 if ( timeout != vpr::Interval::NoWait ) { 00099 ret_val = complete(newStream, &remote_addr, timeout); 00100 } 00101 } 00102 } 00103 // Finish up successful connection. 00104 else if(vpr::Interval::NoWait != timeout) { 00105 ret_val = complete(newStream, &remote_addr, timeout); 00106 } 00107 */ 00108 00109 /* 00110 ** Since complete doesn't do anything really we don't need this 00111 if(ret_val.success()) 00112 { 00113 ret_val = complete(newStream, timeout); 00114 } 00115 */ 00116 00117 return ret_val; 00118 } 00119 00120 // Complete a non-blocking connection 00121 // Try to complete a non-blocking connection. 00122 vpr::ReturnStatus SocketConnector::complete(vpr::SocketStream& newStream, 00123 const vpr::Interval timeout) 00124 { 00125 vpr::ReturnStatus status; 00126 00127 if( newStream.isConnected() ) 00128 { 00129 // XXX: Should this actually be a failure 00130 return vpr::ReturnStatus::Succeed; 00131 } 00132 00133 // If non-blocking, then we can only wait as long as the timeout 00134 if ( ! newStream.isBlocking() ) 00135 { 00136 vpr::IOSys::Handle handle; 00137 vpr::Selector selector; 00138 vpr::Uint16 num_events; 00139 00140 // Use the selector to be informed when the SocketStream object is ready 00141 // to be used. That is, when the object is connected. 00142 handle = newStream.getHandle(); 00143 selector.addHandle(handle); 00144 selector.setIn(handle, vpr::Selector::Read | vpr::Selector::Write); 00145 status = selector.select(num_events, timeout); 00146 00147 // If the selector told us that our handle is ready, we are successfully 00148 // connected. 00149 if ( selector.getOut(handle) & (vpr::Selector::Read | vpr::Selector::Write) ) 00150 { 00151 status = vpr::ReturnStatus::Succeed; 00152 00153 /* 00154 if ( remoteAddr != NULL ) { 00155 (*remoteAddr) = newStream.getRemoteAddr(); 00156 } 00157 */ 00158 } 00159 // else Use the status from the selector 00160 } 00161 else // Not a non-blocking socket 00162 { 00163 vprASSERT(false && "Should not call complete on a non-blocking socket"); 00164 /* 00165 if ( remoteAddr != NULL ) { 00166 (*remoteAddr) = newStream.getRemoteAddr(); 00167 } 00168 */ 00169 } 00170 00171 return status; 00172 } 00173 00174 bool SocketConnector::checkOpen(SocketStream& newStream) 00175 { 00176 vpr::ReturnStatus status; 00177 00178 if (!newStream.isOpen()) 00179 { 00180 status = newStream.open(); 00181 00182 if(!status.success()) 00183 { 00184 vprDEBUG(vprDBG_ALL,vprDBG_CRITICAL_LVL) 00185 << "vpr::Connector:CheckOpen: Failed to open socket\n" 00186 << vprDEBUG_FLUSH; 00187 } 00188 } 00189 00190 return status.success(); 00191 } 00192 00193 // Do preconnection rituals 00194 // - If not bound, then bind to local addr 00195 // - If timeout == 0, then set nonblocking 00196 bool SocketConnector::connectStart(SocketStream& newStream, 00197 vpr::Interval timeout, 00198 const vpr::InetAddr& localAddr) 00199 { 00200 vprASSERT(newStream.isOpen()); 00201 00202 if(!newStream.isBound()) // If we are not bound yet 00203 { 00204 // If timeout is 0, then we are non-blocking 00205 if(vpr::Interval::NoWait == timeout) 00206 { 00207 newStream.setBlocking(false); 00208 } 00209 00210 // Set addr and bind 00211 if(!newStream.setLocalAddr(localAddr).success()) 00212 { 00213 return false; 00214 } 00215 00216 if(!newStream.bind().success()) 00217 { 00218 return false; 00219 } 00220 } 00221 00222 return true; 00223 } 00224 00225 }
1.5.1