From: Asbjorn M. <ste...@us...> - 2002-03-10 17:37:11
|
Update of /cvsroot/epp-rtk/epp-rtk/c++/src/transport In directory usw-pr-cvs1:/tmp/cvs-serv30211 Added Files: epp_TransportTCP.h epp_TransportTCP.cc Log Message: Added new transport, standard TCP/socket. --- NEW FILE: epp_TransportTCP.h --- /************************************************************************ * EPP RTK C++ * Copyright (C) 2001, 2002 The Global Name Registry, Limited * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact information: ep...@gn... * * EPP RTK * The Global Name Registry, Limited * 125 High Holborn * London WC1V 6QA * United Kingdom ************************************************************************/ #ifndef __EPP_TRANSPORTTCP_H #define __EPP_TRANSPORTTCP_H #include <string> #include "epp_TransportConn.h" namespace epptransport { class epp_TransportTCP : public epp_TransportConn { private: char readbuf[16384]; int sockfd; unsigned int pos; int len; unsigned int timeout; bool fillBuf(void); enum { READ = 1, WRITE = 2 }; protected: char rbuf[4096]; public: epp_TransportTCP(); virtual ~epp_TransportTCP() { disconnect(); }; void writeToServer(const string & xml_string); string readFromServer(); bool select(int type) const; void connect(const string & serverName, const unsigned long & serverPort); void connect(); void disconnect(); int getC(); }; }; #endif --- NEW FILE: epp_TransportTCP.cc --- /************************************************************************ * EPP RTK C++ * Copyright (C) 2001, 2002 The Global Name Registry, Limited * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact information: ep...@gn... * * EPP RTK * The Global Name Registry, Limited * 125 High Holborn * London WC1V 6QA * United Kingdom ************************************************************************/ #include "epp_TransportTCP.h" #include <sys/time.h> #include <sys/errno.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <signal.h> #include <stdio.h> #include <unistd.h> #include <netdb.h> using namespace epptransport; // Converts ascii text to in_addr struct. // NULL is returned if the address can not be found. static struct sockaddr_in *atoaddr(const string & address) { struct hostent *host; static struct sockaddr_in saddr; // First try it as aaa.bbb.ccc.ddd. saddr.sin_addr.s_addr = inet_addr(address.c_str()); if ((signed int)saddr.sin_addr.s_addr != -1) { return &saddr; } host = gethostbyname(address.c_str()); if (host != NULL) { memcpy(&saddr.sin_addr.s_addr,host->h_addr,(unsigned int)host->h_length); return &saddr; } return (struct sockaddr_in *)NULL; } epp_TransportTCP::epp_TransportTCP() : epp_TransportConn() { sockfd = -1; pos = 0; len = 0; timeout = 0; readbuf[0] = '\0'; memset(rbuf, 0, sizeof(rbuf)); } bool epp_TransportTCP::fillBuf (void) { if (timeout > 0) { #ifdef SOCKET_DEBUG cerr << "timeout enabled. filling buf" << endl; #endif if (select(READ)) { // move data between pos and len to start of buffer len = ::read(sockfd,&readbuf[pos],(size_t)(sizeof(readbuf)-pos)); if (len <= 0) return false; return true; } else { return false; } } else { // move data between pos and len to start of buffer len = ::read(sockfd,&readbuf[pos],sizeof(readbuf)-pos); if (len <= 0) return false; return true; } } bool epp_TransportTCP::select(int type) const { if (sockfd == -1) return false; for (;;) { fd_set rfds; fd_set wfds; struct timeval tv; tv.tv_sec = (long)timeout; tv.tv_usec = 0; FD_ZERO(&rfds); FD_ZERO(&wfds); if (type & READ) FD_SET(sockfd, &rfds); if (type & WRITE) FD_SET(sockfd, &wfds); #ifdef SOCKET_DEBUG cerr << "before select" << endl; #endif int retval = ::select(sockfd + 1, &rfds, &wfds, (fd_set *)NULL, &tv); #ifdef SOCKET_DEBUG cerr << "after select, retval = " << retval << endl; #endif if (retval > 0) return true; else if (retval == -1 && errno != EINTR) return false; else throw epp_TrException(__FILE__, __LINE__, "Socket timed out"); } } void epp_TransportTCP::writeToServer(const string & xml_string) { string send_xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>"; send_xml += xml_string; int len_ = send_xml.length(); #ifdef SOCKET_DEBUG cerr << "<<< " << send_xml.c_str() << endl; #endif size_t bytes_sent = 0; int this_write; size_t count; if (len_ < 0) len_ = (int)strlen(send_xml.c_str()); count = (unsigned int)len_; while (bytes_sent < count) { do { if (timeout > 0) { if (select(WRITE)) { this_write = write(sockfd, send_xml.c_str(), count - bytes_sent); } else { throw epp_TrException(__FILE__, __LINE__, "Unable to write to server"); } } else { this_write = write(sockfd, send_xml.c_str(), count - bytes_sent); } } while ( (this_write < 0) && (errno == EINTR) ); if (this_write <= 0) { if (errno == EPIPE) { (void)signal(SIGPIPE, SIG_IGN); throw epp_TrException(__FILE__, __LINE__, "Unable to write to server"); } } bytes_sent += (unsigned int)this_write; send_xml += this_write; } } int epp_TransportTCP::getC() { if (len == -1) return -1; if (pos >= (unsigned int)len) { pos = 0; (void)fillBuf(); } if (len <= 0) return -1; return (unsigned int)(readbuf[pos++] & 0xff); } string epp_TransportTCP::readFromServer() { string s; int c = 0; while((c = getC()) != -1) { s += (char)c; if((char)c == '<') { // if "<" if((c = getC()) == -1) break; s += (char)c; if((char)c == '/') { // if "</" if((c = getC()) == -1) break; s += (char)c; if((char)c == 'e') { // if "</e" if((c = getC()) == -1) break; s += (char)c; if((char)c == 'p') { // if "</ep" if((c = getC()) == -1) break; s += (char)c; if((char)c == 'p') { // if "</epp" if((c = getC()) == -1) break; s += (char)c; if((char)c == '>') { // if "</epp>" break; } // if "</epp>" } // if "</epp" } // if "</ep" } // if "</e" } // if "</" } // if "<" } // while return s; } void epp_TransportTCP::connect(const string & serverName, const unsigned long & serverPort) { m_serverName = serverName; m_serverPort = serverPort; connect(); } void epp_TransportTCP::connect() { struct sockaddr_in *address; sockfd = ::socket(AF_INET,(int)SOCK_STREAM, 0); if (sockfd == -1) { throw epp_TrException(__FILE__, __LINE__, "Unable to connect to server"); } address = atoaddr(m_serverName); if (!address) { disconnect(); throw epp_TrException(__FILE__, __LINE__, "Unable to resolve hostname");; } address->sin_family = AF_INET; address->sin_port = htons(m_serverPort); //lint -e740 if (-1== ::connect (sockfd, (struct sockaddr *)address, sizeof(struct sockaddr_in))) { disconnect(); throw epp_TrException(__FILE__, __LINE__, "Unable to connect to server"); } } void epp_TransportTCP::disconnect() { if (sockfd != -1) { while (-1 == ::close(sockfd)) { if (errno == EINTR) continue; return; } } sockfd = -1; return; } |