SocketConnector.cpp

Go to the documentation of this file.
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 }

Generated on Thu Jan 4 10:52:10 2007 for VR Juggler Portable Runtime by  doxygen 1.5.1