1 //============================================================================== 2 // 3 // This file is part of GPSTk, the GPS Toolkit. 4 // 5 // The GPSTk is free software; you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published 7 // by the Free Software Foundation; either version 3.0 of the License, or 8 // any later version. 9 // 10 // The GPSTk is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public 16 // License along with GPSTk; if not, write to the Free Software Foundation, 17 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA 18 // 19 // This software was developed by Applied Research Laboratories at the 20 // University of Texas at Austin. 21 // Copyright 2004-2020, The Board of Regents of The University of Texas System 22 // 23 //============================================================================== 24 25 //============================================================================== 26 // 27 // This software was developed by Applied Research Laboratories at the 28 // University of Texas at Austin, under contract to an agency or agencies 29 // within the U.S. Department of Defense. The U.S. Government retains all 30 // rights to use, duplicate, distribute, disclose, or release this software. 31 // 32 // Pursuant to DoD Directive 523024 33 // 34 // DISTRIBUTION STATEMENT A: This software has been approved for public 35 // release, distribution is unlimited. 36 // 37 //============================================================================== 38 39 #include <cstring> 40 41 #include <sstream> 42 #include <errno.h> 43 #include <stdlib.h> 44 45 #include <unistd.h> 46 #include <netdb.h> 47 #include <fcntl.h> 48 #include <sys/file.h> 49 50 #include <stdio.h> 51 #if !defined(unix) && !defined(__unix__) && !defined(__APPLE__) 52 #include <winsock.h> 53 #else 54 #include <sys/types.h> 55 #include <sys/socket.h> 56 #include <netinet/in.h> 57 #include <netinet/tcp.h> 58 #endif 59 60 #include <arpa/inet.h> 61 62 #include "TCPStreamBuff.hpp" 63 64 using namespace std; 65 66 namespace gpstk 67 { 68 //------------------------------------------------------------------------ IPaddress(const string & host_name)69 IPaddress::IPaddress(const string& host_name) 70 { 71 // If the address is in dotted quad notation, this will work. 72 address = inet_addr(host_name.c_str()); 73 if ( address != (uint32_t)(-1) ) 74 return; 75 76 struct hostent *host_ptr = ::gethostbyname(host_name.c_str()); 77 if( host_ptr == 0 ) 78 { 79 cout << "Host name '" << host_name << "' cannot be resolved"; 80 return; 81 } 82 if( host_ptr->h_addrtype != AF_INET ) 83 { 84 cout << "Host name '" << host_name 85 << "' isn't an AF_INET address" << endl; 86 return; 87 } 88 89 memcpy(&address, host_ptr->h_addr, sizeof(address)); 90 } 91 92 93 //------------------------------------------------------------------------ operator <<(ostream & os,const IPaddress addr)94 ostream& operator<<(ostream& os, const IPaddress addr) 95 { 96 struct hostent * const host_ptr = 97 ::gethostbyaddr((char *)&addr.address, 98 sizeof(addr.address), AF_INET); 99 if( host_ptr != 0 ) 100 return os << host_ptr->h_name; 101 102 // Reverse DNS failed, print in the dot notation 103 char buffer[80]; 104 const unsigned int native_addr = ntohl(addr.address); 105 sprintf(buffer,"%0d.%0d.%0d.%0d", (native_addr >> 24) & 0xff, 106 (native_addr >> 16) & 0xff, (native_addr >> 8) & 0xff, 107 native_addr & 0xff); 108 return os << buffer; 109 } 110 111 //------------------------------------------------------------------------ SocketAddr(const IPaddress host,const short port_no)112 SocketAddr::SocketAddr(const IPaddress host, const short port_no) 113 { 114 sin_family = AF_INET; 115 sin_port = htons((short)port_no); 116 sin_addr.s_addr = host.net_addr(); 117 } 118 operator <<(ostream & os,const SocketAddr & addr)119 ostream& operator<<(ostream& os, const SocketAddr& addr) 120 { 121 return os << IPaddress(addr.sin_addr.s_addr) << ':' 122 << (unsigned short)ntohs((short)addr.sin_port); 123 } 124 125 126 //------------------------------------------------------------------------ connect(const SocketAddr target_address)127 int TCPStreamBuff::connect(const SocketAddr target_address) 128 { 129 if (is_open()) 130 return 0; 131 132 handle = socket(AF_INET,SOCK_STREAM,0); 133 if (!handle) 134 return -1; 135 136 // set_blocking_io(false); 137 138 int connect_status = -1; 139 for (int i=0; i<5 && connect_status != 0; i++) 140 { 141 connect_status = ::connect(handle, (sockaddr *)target_address, 142 sizeof(target_address)); 143 } 144 if (connect_status !=0) 145 return connect_status; 146 147 // We do our own buffering... 148 char off=0; 149 ::setsockopt(handle, IPPROTO_TCP, TCP_NODELAY, &off, sizeof(off)); 150 return 0; 151 } 152 153 154 //------------------------------------------------------------------------ 155 // Take a file handle (which is supposed to be a listening socket), accept 156 // a connection if any, and return a TCPStreamBuff for that connection. On exit, 157 // peeraddr would be an addr of the connected peer. accept(int listening_socket,SocketAddr & peeraddr)158 int TCPStreamBuff::accept(int listening_socket, SocketAddr& peeraddr) 159 { 160 // do nothing if we are already connected 161 if (is_open()) 162 return 0; 163 164 for(;;) 165 { 166 socklen_t target_addr_size = sizeof(peeraddr); 167 handle = ::accept(listening_socket,(sockaddr *)peeraddr, 168 &target_addr_size); 169 if (handle >= 0) 170 break; // Successfully accepted the connection 171 if (errno == EAGAIN || errno == EINTR) 172 cout << "to be implimented" << endl; 173 else 174 return 0; 175 } 176 177 // We do our own buffering... 178 char off=0; 179 ::setsockopt(handle, IPPROTO_TCP, TCP_NODELAY, &off, sizeof(off)); 180 return 0; 181 } 182 183 } // end of namespace 184