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
Copyright © 2001 SL_OpenSource XML Project. All Rights Reserved