Files
OpenSceneGraph/src/osgPlugins/net/sockinet.cpp
Don BURNS 2a3f7b2799 Added the .net plug-in. This allows the reading of files by
specifying <host>:file.<ext>.net for example:

    osgviewer osgcvs.no-ip.com:OSGModels/cow.osg.net
2004-08-28 07:25:21 +00:00

440 lines
10 KiB
C++

// sockinet.C -*- C++ -*- socket library
// Copyright (C) 2002 Herbert Straub
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// Copyright (C) 1992-1996 Gnanasekaran Swaminathan <gs4t@virginia.edu>
//
// Permission is granted to use at your own risk and distribute this software
// in source and binary forms provided the above copyright notice and this
// paragraph are preserved on all copies. This software is provided "as is"
// with no express or implied warranty.
//
// Version: 12Jan97 1.11
// 2002-07-25 Version 1.2 (C) Herbert Straub
// Adding improved Error Handling in sockerr class
// sockinetaddr::setport if the first character of the port parameter is a
// digit, then the parameter is interpreted as a number
// 2002-07-28 Version 1.2 (C) Herbert Straub
// Eliminating sorry_about_global_temp inititialisation. This don't work
// in combination with NewsCache. My idea is: initializing the classes with (0)
// and in the second step call ios::init (sockinetbuf *) and iosockstream::init ...
// The constructors of isockinet, osockinet and iosockinet are changed.
#include "sockinet.h"
#if defined(__APPLE)
typedef int socklen_t;
#endif
#ifndef WIN32
extern "C" {
# include <netdb.h>
# include <sys/time.h>
# include <sys/socket.h>
# include <stdlib.h>
# include <unistd.h>
# include <errno.h>
# include <netinet/tcp.h>
# include <netinet/in.h>
# include <netinet/in.h>
# include <arpa/inet.h>
}
#else
# define socklen_t int
# define EADDRNOTAVAIL WSAEADDRNOTAVAIL
# define EADDRINUSE WSAEADDRINUSE
# define ENOPROTOOPT WSAENOPROTOOPT
#endif // !WIN32
void herror(const char*);
sockinetaddr::sockinetaddr ()
{
sin_family = sockinetbuf::af_inet;
sin_addr.s_addr = htonl(INADDR_ANY);
sin_port = 0;
}
sockinetaddr::sockinetaddr(unsigned long addr, int port_no)
// addr and port_no are in host byte order
{
sin_family = sockinetbuf::af_inet;
sin_addr.s_addr = htonl(addr);
sin_port = htons(port_no);
}
sockinetaddr::sockinetaddr(unsigned long addr, const char* sn, const char* pn)
// addr is in host byte order
{
sin_family = sockinetbuf::af_inet;
sin_addr.s_addr = htonl (addr); // Added by cgay@cs.uoregon.edu May 29, 1993
setport(sn, pn);
}
sockinetaddr::sockinetaddr (const char* host_name, int port_no)
// port_no is in host byte order
{
setaddr(host_name);
sin_port = htons(port_no);
}
sockinetaddr::sockinetaddr(const char* hn, const char* sn, const char* pn)
{
setaddr(hn);
setport(sn, pn);
}
sockinetaddr::sockinetaddr (const sockinetaddr& sina)
{
sin_family = sockinetbuf::af_inet;
sin_addr.s_addr = sina.sin_addr.s_addr;
sin_port = sina.sin_port;
}
void sockinetaddr::setport(const char* sn, const char* pn)
{
if (isdigit (*sn)) {
sin_port = htons(atoi(sn));
} else {
servent* sp = getservbyname(sn, pn);
if (sp == 0) throw sockerr (EADDRNOTAVAIL, "sockinetaddr::setport");
sin_port = sp->s_port;
}
}
int sockinetaddr::getport () const
{
return ntohs (sin_port);
}
void sockinetaddr::setaddr(const char* host_name)
{
if ( (sin_addr.s_addr = inet_addr(host_name)) == INADDR_NONE) {
hostent* hp = gethostbyname(host_name);
if (hp == 0) throw sockerr (EADDRNOTAVAIL, "sockinetaddr::setaddr");
memcpy(&sin_addr, hp->h_addr, hp->h_length);
sin_family = hp->h_addrtype;
} else
sin_family = sockinetbuf::af_inet;
}
const char* sockinetaddr::gethostname () const
{
if (sin_addr.s_addr == htonl(INADDR_ANY)) {
static char hostname[64];
if (::gethostname(hostname, 63) == -1) return "";
return hostname;
}
hostent* hp = gethostbyaddr((const char*) &sin_addr,
sizeof(sin_addr),
family());
if (hp == 0) return "";
if (hp->h_name) return hp->h_name;
return "";
}
sockinetbuf::sockinetbuf (const sockbuf::sockdesc& sd)
: sockbuf (sd.sock)
{}
sockinetbuf::sockinetbuf(sockbuf::type ty, int proto)
: sockbuf (af_inet, ty, proto)
{}
sockinetaddr sockinetbuf::localaddr() const
{
sockinetaddr sin;
int len = sin.size();
if (::getsockname(rep->sock, sin.addr (), (socklen_t*) // LN
&len) == -1)
throw sockerr (errno, "sockinetbuf::localaddr");
return sin;
}
int sockinetbuf::localport() const
{
sockinetaddr sin = localaddr();
if (sin.family() != af_inet) return -1;
return sin.getport();
}
const char* sockinetbuf::localhost() const
{
sockinetaddr sin = localaddr();
if (sin.family() != af_inet) return "";
return sin.gethostname();
}
sockinetaddr sockinetbuf::peeraddr() const
{
sockinetaddr sin;
int len = sin.size();
if (::getpeername(rep->sock, sin.addr (), (socklen_t*) // LN
&len) == -1)
throw sockerr (errno, "sockinetbuf::peeraddr");
return sin;
}
int sockinetbuf::peerport() const
{
sockinetaddr sin = peeraddr();
if (sin.family() != af_inet) return -1;
return sin.getport();
}
const char* sockinetbuf::peerhost() const
{
sockinetaddr sin = peeraddr();
if (sin.family() != af_inet) return "";
return sin.gethostname();
}
void sockinetbuf::bind_until_success (int portno)
// a. bind to (INADDR_ANY, portno)
// b. if success return
// c. if failure and errno is EADDRINUSE, portno++ and go to step a.
{
for (;;) {
try {
bind (portno++);
}
catch (sockerr e) {
// if (e.errno () != EADDRINUSE) throw;
if (e.serrno () != EADDRINUSE) throw; // LN
continue;
}
break;
}
}
void sockinetbuf::bind (sockAddr& sa)
{
sockbuf::bind (sa);
}
void sockinetbuf::bind (int port_no)
{
sockinetaddr sa ((long unsigned int) // LN
INADDR_ANY, port_no);
bind (sa);
}
void sockinetbuf::bind (unsigned long addr, int port_no)
// address and portno are in host byte order
{
sockinetaddr sa (addr, port_no);
bind (sa);
}
void sockinetbuf::bind (const char* host_name, int port_no)
{
sockinetaddr sa (host_name, port_no);
bind (sa);
}
void sockinetbuf::bind (unsigned long addr,
const char* service_name,
const char* protocol_name)
{
sockinetaddr sa (addr, service_name, protocol_name);
bind (sa);
}
void sockinetbuf::bind (const char* host_name,
const char* service_name,
const char* protocol_name)
{
sockinetaddr sa (host_name, service_name, protocol_name);
bind (sa);
}
void sockinetbuf::connect (sockAddr& sa)
{
sockbuf::connect (sa);
}
void sockinetbuf::connect (unsigned long addr, int port_no)
// address and portno are in host byte order
{
sockinetaddr sa (addr, port_no);
connect (sa);
}
void sockinetbuf::connect (const char* host_name, int port_no)
{
sockinetaddr sa (host_name, port_no);
connect (sa);
}
void sockinetbuf::connect (unsigned long addr,
const char* service_name,
const char* protocol_name)
{
sockinetaddr sa (addr, service_name, protocol_name);
connect (sa);
}
void sockinetbuf::connect (const char* host_name,
const char* service_name,
const char* protocol_name)
{
sockinetaddr sa (host_name, service_name, protocol_name);
connect (sa);
}
sockbuf::sockdesc sockinetbuf::accept ()
{
return sockbuf::accept ();
}
sockbuf::sockdesc sockinetbuf::accept (sockAddr& sa)
{
return sockbuf::accept (sa);
}
sockbuf::sockdesc sockinetbuf::accept (unsigned long addr,
int port_no)
{
sockinetaddr sa (addr, port_no);
return accept (sa);
}
sockbuf::sockdesc sockinetbuf::accept (const char* host_name,
int port_no)
{
sockinetaddr sa (host_name, port_no);
return accept (sa);
}
bool sockinetbuf::tcpnodelay () const
{
struct protoent* proto = getprotobyname ("tcp");
if (proto == 0) throw sockerr (ENOPROTOOPT, "sockinetbuf::tcpnodelay");
int old = 0;
getopt (TCP_NODELAY, &old, sizeof (old), proto->p_proto);
return old!=0;
}
bool sockinetbuf::tcpnodelay (bool set) const
{
struct protoent* proto = getprotobyname ("tcp");
if (proto == 0) throw sockerr (ENOPROTOOPT, "sockinetbuf::tcpnodelay");
int old = 0;
int opt = set;
getopt (TCP_NODELAY, &old, sizeof (old), proto->p_proto);
setopt (TCP_NODELAY, &opt, sizeof (opt), proto->p_proto);
return old!=0;
}
isockinet::isockinet (const sockbuf::sockdesc& sd)
: ios(0), isockstream(0)
{
sockinetbuf *t = new sockinetbuf (sd);
ios::init (t);
isockstream::init (t);
}
isockinet::isockinet (sockbuf::type ty, int proto)
: ios (0), isockstream(0)
{
sockinetbuf *t = new sockinetbuf (ty, proto);
ios::init (t);
isockstream::init (t);
}
isockinet::isockinet (const sockinetbuf& sb)
: ios (0), isockstream(0)
{
sockinetbuf *t = new sockinetbuf (sb);
ios::init (t);
isockstream::init (t);
}
isockinet::~isockinet ()
{
delete ios::rdbuf ();
}
osockinet::osockinet (const sockbuf::sockdesc& sd)
: ios (0), osockstream(0)
{
sockinetbuf *t = new sockinetbuf (sd);
ios::init (t);
osockstream::init (t);
}
osockinet::osockinet (sockbuf::type ty, int proto)
: ios (0), osockstream(0)
{
sockinetbuf *t = new sockinetbuf (ty, proto);
ios::init (t);
osockstream::init (t);
}
osockinet::osockinet (const sockinetbuf& sb)
: ios (0), osockstream(0)
{
sockinetbuf *t = new sockinetbuf (sb);
ios::init (t);
osockstream::init (t);
}
osockinet::~osockinet ()
{
delete ios::rdbuf ();
}
iosockinet::iosockinet (const sockbuf::sockdesc& sd)
: ios (0), iosockstream(0)
{
sockinetbuf *t = new sockinetbuf(sd);
ios::init (t);
iosockstream::init (t);
}
iosockinet::iosockinet (sockbuf::type ty, int proto)
: ios (0), iosockstream (0)
{
sockinetbuf *t = new sockinetbuf (ty, proto);
ios::init (t);
iosockstream::init (t);
}
iosockinet::iosockinet (const sockinetbuf& sb)
: ios (0), iosockstream(0)
{
sockinetbuf *t = new sockinetbuf (sb);
ios::init (t);
iosockstream::init (t);
}
iosockinet::~iosockinet ()
{
delete ios::rdbuf ();
}