Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

Channel.cpp

Go to the documentation of this file.
00001 /* -*- C++ -*- */
00002 
00003 /*
00004  * The Apache Software License, Version 1.1
00005  *
00006  *
00007  * Copyright (c) 2002 The Apache Software Foundation.  All rights
00008  * reserved.
00009  *
00010  * Redistribution and use in source and binary forms, with or without
00011  * modification, are permitted provided that the following conditions
00012  * are met:
00013  *
00014  * 1. Redistributions of source code must retain the above copyright
00015  *    notice, this list of conditions and the following disclaimer.
00016  *
00017  * 2. Redistributions in binary form must reproduce the above copyright
00018  *    notice, this list of conditions and the following disclaimer in
00019  *    the documentation and/or other materials provided with the
00020  *    distribution.
00021  *
00022  * 3. The end-user documentation included with the redistribution,
00023  *    if any, must include the following acknowledgment:
00024  *       "This product includes software developed by the
00025  *        Apache Software Foundation (http://www.apache.org/)."
00026  *    Alternately, this acknowledgment may appear in the software itself,
00027  *    if and wherever such third-party acknowledgments normally appear.
00028  *
00029  * 4. The names "SOAP" and "Apache Software Foundation" must
00030  *    not be used to endorse or promote products derived from this
00031  *    software without prior written permission. For written
00032  *    permission, please contact apache@apache.org.
00033  *
00034  * 5. Products derived from this software may not be called "Apache",
00035  *    nor may "Apache" appear in their name, without prior written
00036  *    permission of the Apache Software Foundation.
00037  *
00038  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
00039  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00040  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00041  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
00042  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00043  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00044  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
00045  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00046  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00047  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
00048  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00049  * SUCH DAMAGE.
00050  * ====================================================================
00051  *
00052  * This software consists of voluntary contributions made by many
00053  * individuals on behalf of the Apache Software Foundation.  For more
00054  * information on the Apache Software Foundation, please see
00055  * <http://www.apache.org/>.
00056  */
00057 
00058 /*
00059  *
00060  *
00061  * @author Lilantha Darshana (lilantha@erunway.com)
00062  *
00063  */
00064 
00065 #include "Platform.hpp"
00066 #include "Channel.hpp"
00067 #include <iostream>
00068 
00069 #include "Transport.hpp"
00070 
00071 
00076 
00077 Channel::Channel() : m_Sock(INVALID_SOCKET)
00078 {
00079 
00080 }
00081 
00082 Channel::~Channel()
00083 {
00084     CloseChannel();
00085 }
00086 
00087 
00097 
00098 bool Channel::Open(std::string& p_RemoteNode, unsigned short p_RemoteEnd) throw (ChannelException)
00099 {
00100     m_RemoteNode = p_RemoteNode;
00101     m_RemoteEnd  = p_RemoteEnd;
00102 
00103     if(!Init())
00104         throw ChannelException("Cannot initialize a channel to the remote end");
00105 
00106     sockaddr_in clAddr, svAddr;           
00107 
00108     if ((m_Sock = socket(PF_INET, SOCK_STREAM, 0)) != INVALID_SOCKET)
00109     {
00110         clAddr.sin_family = AF_INET;     // AF_INET (address family Internet).
00111         clAddr.sin_port   = 0;           // No Specify Port required
00112         clAddr.sin_addr.s_addr = INADDR_ANY;
00113 
00114         if (bind(m_Sock, (struct sockaddr*) &clAddr, sizeof(clAddr)) == SOCKET_ERROR)
00115         {
00116             Error("Error - Binding");
00117             CloseChannel();
00118             throw ChannelException("Cannot open a channel to the remote end, shutting down the channel");
00119         }
00120 
00121         // Although the above fragment makes use of the bind() API, it would be
00122         // just as effective to skip over this call as there are no specific
00123         // local port ID requirements for this client. The only advantage that
00124         // bind() offers is the accessibility of the port which the system chose
00125         // via the .sin_port member of the cli_addr structure which will be set
00126         // upon success of the bind() call.
00127 
00128         svAddr.sin_family = AF_INET;
00129         svAddr.sin_port   = htons(m_RemoteEnd);
00130 
00131         struct hostent*  pHostEntry = NULL;
00132 
00133         // probably this is the host-name of the server we are connecting to
00134         if((pHostEntry = gethostbyname(m_RemoteNode.c_str())))
00135         {
00136             svAddr.sin_addr.s_addr = ((struct in_addr *)pHostEntry->h_addr)->s_addr;
00137         }
00138         else
00139         {
00140             // no this is the IP address
00141             svAddr.sin_addr.s_addr = inet_addr(m_RemoteNode.c_str());   
00142         }
00143 
00144         // connect to the remote server.
00145         if (connect(m_Sock,(struct sockaddr*)&svAddr, sizeof(svAddr)) == SOCKET_ERROR)
00146         {
00147             Error("Sockets error Couldn't connect socket.");
00148             CloseChannel();
00149             throw ChannelException("Cannot open a channel to the remote end, shutting down the channel");
00150         }
00151     }
00152     else
00153     {
00154         Error("Sockets error Couldn't create socket.");
00155         CloseChannel();
00156         throw ChannelException("Cannot open a channel");
00157     }
00158     return true;
00159 }
00160 
00166 
00167 bool Channel::Init()
00168 {
00169 #if defined(WIN32)
00170 
00171     WSADATA wsaData;            // contains vendor-specific information, such as the
00172                                 // maximum number of sockets available and the maximum
00173                                 // datagram size.
00174 
00175     if(WSAStartup(WS_VERSION_REQD, &wsaData))  //Filled by Windows Sockets DLLs
00176     {
00177         m_LastErr = "WinSock DLL not responding.";
00178         Error((char *)m_LastErr.c_str());
00179         return false;
00180     }
00181     else
00182     { 
00183         // Query to see whether the available version matches what we need
00184         if (( LOBYTE (wsaData.wVersion) < WS_VERSION_MAJOR()) ||
00185              (LOBYTE (wsaData.wVersion) == WS_VERSION_MAJOR() &&
00186               HIBYTE (wsaData.wVersion) < WS_VERSION_MINOR()))
00187         {
00188             char buf[100];
00189             sprintf(buf,"Windows Sockets version %d.%d not supported by winsock2.dll",
00190                         LOBYTE (wsaData.wVersion), HIBYTE (wsaData.wVersion));
00191             Error(buf);
00192             CloseChannel();
00193             return false;
00194         }
00195     }
00196 #else
00197 
00198     // other OS specific Intitialization goes here
00199 #endif
00200     return true;
00201 }
00202 
00210 const Channel& Channel::operator << (const std::string& msg)
00211 {
00212     if(INVALID_SOCKET == m_Sock) 
00213     {
00214         Error("Writing cannot be done without having a open socket to remote end.");
00215         throw ChannelException("Output streaming error on undefined channel; please open the channel first");
00216     }
00217 
00218     int size = msg.size(), nByteSent;
00219     
00220     if((nByteSent = send(m_Sock, (char *)msg.c_str(), size, MSG_DONTROUTE )) == SOCKET_ERROR)
00221     {
00222         Error("Output streaming error while writing data.");
00223         CloseChannel();
00224         throw ChannelException("Output streaming error on Channel while writing data");
00225     }
00226 
00227     return *this;
00228 }
00229 
00235 
00236 const Channel& Channel::operator >> (std::string& msg)
00237 {
00238     if(INVALID_SOCKET == m_Sock) 
00239     {
00240         Error("Reading cannot be done without having a open socket.");
00241         throw ChannelException("Input streaming error on undefined channel; please open the channel first");
00242     }
00243 
00244     int nByteRecv = 0;
00245     const int BUF_SIZE = 4096;
00246     char buf[BUF_SIZE];
00247     
00248     do  // Manage multiple chuncks of the message
00249     {
00250         if ((nByteRecv = recv(m_Sock, (char *) &buf, BUF_SIZE - 1, 0)) == SOCKET_ERROR)
00251         {
00252             Error("Channel error while getting data.");
00253             CloseChannel();
00254             throw ChannelException("Input streaming error on Channel while getting data");
00255         }
00256 
00257         if(nByteRecv)
00258         {
00259             buf[nByteRecv + 1] = '\0';  // got a part of the message, so add it to form 
00260             msg += buf;                 // the whole message
00261 
00262             //Validate according to the transport; check whether we are in a position to return.
00263             if (!m_pTransportHandler->GetStatus(msg)) 
00264                 break;
00265         }
00266         else
00267             break; // we have the whole message or an error has occured
00268      }
00269      while (true);
00270 
00271      return *this;
00272 }
00273 
00278 
00279 void Channel::CloseChannel()
00280 {
00281 #ifdef WIN32
00282     if(INVALID_SOCKET != m_Sock)
00283         closesocket(m_Sock);
00284     
00285     // Check for any possible error conditions from WSACleanup() and report
00286     // them before exiting, as this information might indicate a network
00287     // layer problem in the system.
00288 
00289     WSACleanup();
00290 #else
00291     if(INVALID_SOCKET != m_Sock)
00292         close(m_Sock);
00293 
00294 #endif
00295 }
00296 
00301 
00302 void Channel::Error(const char * err)
00303 {
00304 #ifdef _DEBUG
00305     std::cerr << err << std::endl;
00306 #endif
00307 }
00308 
00309 
00310 
00311 
Axis C++ Client Lib - User's Guide

Copyright © 2001 SL_OpenSource XML Project. All Rights Reserved