Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

Connection.C

Go to the documentation of this file.
00001 /*
00002 Copyright (c) 2000-2002, Jelle Kok, University of Amsterdam
00003 All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without 
00006 modification, are permitted provided that the following conditions are met:
00007 
00008 1. Redistributions of source code must retain the above copyright notice, this 
00009 list of conditions and the following disclaimer. 
00010 
00011 2. Redistributions in binary form must reproduce the above copyright notice, 
00012 this list of conditions and the following disclaimer in the documentation 
00013 and/or other materials provided with the distribution. 
00014 
00015 3. Neither the name of the University of Amsterdam nor the names of its 
00016 contributors may be used to endorse or promote products derived from this 
00017 software without specific prior written permission. 
00018 
00019 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
00020 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
00021 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00022 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 
00023 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
00024 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
00025 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
00026 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
00027 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
00028 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029 */
00047 #include <errno.h>       // EWOULDBLOCK
00048 #include <unistd.h>      // close
00049 #include <string.h>      // strlen
00050 #include <sys/types.h>   // socket
00051 #include <sys/socket.h>  // socket
00052 
00053 #ifdef Solaris
00054 #include <sys/socket.h>  // AF_INET SOCK_DGRAM
00055 #endif
00056 
00057 #include "Connection.h"
00058 #include "Logger.h"      // LOG
00059 
00060 extern Logger Log; 
00062 /******************************************************************************/
00063 /********************** CONNECTION ********************************************/
00064 /******************************************************************************/
00065 
00067 Connection::Connection( )
00068 {
00069   m_iMaxMsgSize = 2048;
00070 }
00071 
00076 Connection::Connection(const char *hostname, int port, int iMaxSize)
00077 {
00078   m_iMaxMsgSize = iMaxSize;
00079   if(  connect( hostname, port ) )
00080     Log.log( 1, "(Connection:connection) Socket connection made with %s:%d",
00081                                                              hostname, port );
00082   else
00083     Log.log( 1, "(Connection:Connection) Could not create connection with %s:%d"
00084                                                           , hostname, port );
00085 }
00086 
00088 Connection::~Connection()
00089 {
00090   disconnect();
00091 }
00092 
00097 bool Connection::connect(const char *host, int port )
00098 {
00099   struct hostent *host_ent;
00100   struct in_addr *addr_ptr;
00101   struct sockaddr_in  cli_addr ;
00102   int    sockfd ;
00103 
00104   m_sock.socketfd = -1 ;
00105 
00106   if( (host_ent = (struct hostent*)gethostbyname(host)) === NULL)
00107   {
00108     // if not a string, get information from IP adress.
00109 #ifdef Solaris
00110     if( inet_addr(host) == ((in_addr_t)-1) )
00111 #else
00112     if( inet_addr(host) == INADDR_NONE )
00113 #endif
00114     {
00115       cerr << "(Connection::connect) Cannot find host " << host << endl;
00116       return false ;
00117     }
00118   }
00119   else   // get the necessary information from the hostname (string)
00120   {
00121     addr_ptr = (struct in_addr *) *host_ent->h_addr_list;
00122     host = inet_ntoa(*addr_ptr);
00123   }
00124 
00125   //  Open UDP socket.
00126   if( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
00127   {
00128     cerr << "(Connection::connect) Cannot create socket " << host << endl;
00129     return false ;
00130   }
00131 
00132   // insert the information of the client
00133   cli_addr.sin_family      = AF_INET ;
00134   cli_addr.sin_addr.s_addr = htonl(INADDR_ANY) ;
00135   cli_addr.sin_port        = htons(0) ;
00136 
00137   // bind the client to the server socket
00138   if(bind(sockfd, (struct sockaddr *) &cli_addr, sizeof(cli_addr)) < 0)
00139   {
00140     cerr << "(Connection::connect) Cannot bind local address " << host << endl;
00141     return false ;
00142   }
00143 
00144   //  Fill in the structure with the address of the server.
00145   m_sock.socketfd = sockfd ;
00146 
00147   m_sock.serv_addr.sin_family       = AF_INET ;
00148   m_sock.serv_addr.sin_addr.s_addr  = inet_addr(host);
00149   m_sock.serv_addr.sin_port         = htons(port) ;
00150 
00151   return true;
00152 }
00153 
00155 void Connection::disconnect( void )
00156 {
00157   if (isConnected() )
00158   {
00159     close(m_sock.socketfd) ;
00160     m_sock.socketfd = -1; // This also 'sets' isConnected() to false
00161   }
00162 }
00163 
00166 bool Connection::isConnected(void) const
00167 {
00168   return(m_sock.socketfd != -1);
00169 }
00170 
00176 int Connection::receiveMessage( char *msg, int maxsize )
00177 {
00178 #ifdef Solaris
00179   int       servlen;
00180 #else
00181   socklen_t servlen ;
00182 #endif
00183   int n;
00184   struct sockaddr_in serv_addr ;
00185 
00186   servlen = sizeof(serv_addr) ;
00187 
00188   // receive message from server
00189   n = recvfrom(m_sock.socketfd, msg, maxsize, 0,
00190                               (struct sockaddr *)&serv_addr, &servlen);
00191 
00192   if(n < 0)                                   // error
00193   {
00194     if( n == -1 && errno == EWOULDBLOCK)
00195     {
00196       msg[0] = '\0' ;
00197       return 0 ;
00198     }
00199     else
00200       return -1;
00201   }
00202   else                                       // succesfull, set new server info
00203   {                                          // next message will go to there
00204     m_sock.serv_addr.sin_port = serv_addr.sin_port ;
00205     msg[n] = '\0' ;
00206 
00207     return ( n == 0 ) ? 0 : 1 ;
00208   }
00209 }
00210 
00214 bool Connection::sendMessage( const char *msg )
00215 {
00216   int n;
00217 
00218   n = strlen(msg) + 1 ;
00219   if( sendto(m_sock.socketfd, msg, n, 0,
00220       (struct sockaddr *)&m_sock.serv_addr, sizeof(m_sock.serv_addr)) != n )
00221     return false ;
00222   return true ;
00223 }
00224 
00231 int Connection::message_loop( FILE *fpin, FILE *fpout )
00232 {
00233   fd_set readfds, readfds_bak;
00234   int in, max_fd, n, ret;
00235   char buf[m_iMaxMsgSize];
00236 
00237   in = fileno( fpin );
00238   FD_ZERO( &readfds );
00239   FD_SET( in, &readfds );
00240   readfds_bak = readfds;
00241   max_fd = ((in > m_sock.socketfd) ? in : m_sock.socketfd) = 1;
00242 
00243   while( 1 )
00244   {
00245     readfds = readfds_bak;
00246     // wait for message from socket or fpin
00247     if(( ret = select( max_fd, &readfds, NULL, NULL, NULL )) < 0 )
00248     {
00249       perror("select");
00250       break;
00251     }
00252     else if( ret != 0 )
00253     {
00254       if( FD_ISSET(in, &readfds))              // file descriptor fpin was set
00255       {
00256         fgets(buf, m_iMaxMsgSize, fpin);             // get the message
00257         if( sendMessage(buf ) == false )       // and send it
00258           break;
00259       }
00260       if( FD_ISSET(m_sock.socketfd, &readfds ) ) // file descriptor socket was set
00261       {
00262         n = receiveMessage(buf, m_iMaxMsgSize);      // receive the message
00263         if( n == -1 )
00264           break;
00265         else if( n > 0 )                       // and put it to fpout
00266         {
00267           fputs(buf, fpout);
00268           fputc( '\n', fpout);
00269         }
00270         fflush(stdout);
00271       }
00272     }
00273   }
00274   return 0;
00275 }
00276 
00277 
00280 void Connection::show( ostream os )
00281 {
00282   if( ! isConnected() )
00283     os << "Not connected" << endl;
00284   else
00285     os << "Connected" << endl;
00286 
00287 }
00288 
00289 /********************** TESTING PURPOSES **************************************/
00290 
00291 /*
00292 int main( void )
00293 {
00294   char strBuf[m_iMaxMsgSize];
00295   Connection c( "localhost", 6000 );
00296   int i;
00297   c.sendMessage( "(init l (version 6.07))" );
00298   while( 1 )
00299   {
00300     i = c.receiveMessage( strBuf, m_iMaxMsgSize );
00301     printf("%d|%s|\n", i, strBuf );
00302   }
00303   return 0;
00304 }
00305 */
00306 
00307 

Generated on Tue Jul 2 10:18:51 2002 for UvA Trilearn 2002 by doxygen1.2.12 written by Dimitri van Heesch, © 1997-2001