Endpoint

# Endpoint C++ Socket Library

Endpoint is a C++ class which uses Berkeley sockets to communicate with hosts via the Internet, through IPv4 or IPv6, using TCP or UDP or raw IP, on Win32 or Unix operating systems. Originally written for developing peer-to-peer applications, the simple philosophy behind Endpoint is of choice and portability and consistency:

- Protocol-family independence - IPv4 or IPv6, transparently
- Socket-type independence - UDP or TCP, client or server created similarly
- Platform-indepedence - works on Win32 and Unix

Additionally, data is data. It shouldn't matter how it gets there, via IPv4 or IPv6, on a Win32 or Unix platform. The addressing and connection establishment is the tough part, which this class hierarchy tries to address. New protocol family-independent calls are used, nullifying the need to port to IPv6 once IPv6 becomes more widely used.

Also, Endpoint is to be optimized for typical cases, while still retaining desired functionality. Byte counters are an example of this, as is multiple addresses per host. In the future, perhaps multicasting will be transparently available.

For more information, read below or refer to Tips and Tricks or the EndpointAddress documentation. To download, go to file releases.

## Platforms

Endpoint has been compiled and tested successfully on the following operating systems:

- FreeBSD 5.1-CURRENT, G++ 3.3.1
- FreeBSD 4.8-STABLE, G++ 2.95.4
- Microsoft Windows XP, VC++ 6.0 - raw sockets tested
- Microsoft Windows 2000, VC++ 6.0
- Microsoft Windows Me, VC++ 6.0

Portability is a major goal. Testers welcome.

## Feature List

Currently:

- UDP, TCP, IPv4 raw sockets
- Active or passive open (CLIENT or server)
- Protocol independence
- IPv4 or IPv6 with automatic getaddrinfo() DNS resolution
- Automatic creation IPv4 header for raw sockets unless RAW_RAW given
- Automatic creation of UDP header for RAW_UDP sockets, with proper ports
- Automatic creation of ICMP header, "code,type" dest port specification
- Optional `Endpoint::g_raw_sockfd`, set this to a raw socket descriptor and all raw sockets will use it. Allows Endpoint to be ran without root priviledges. Can also be passed through `RAWSOCKFD` environment variable if `setup_raw()` is called first.
- Socket options, SetOptOn, uses setsockopt
- Error handling

Not implemented (yet):

- A pluggable mechanism for registering creation of new layer-4 raw protocols so for example, create_igmp() creates raw IGMP packet headers. Extensive as possible. (Currently only UDP and ICMP create headers for you). Perhaps Libnet would be better for this purpose.
- A shorter method of creating RAW sockets. Endpoint ep(RAW);
- Easily usable I/O: ep << "foo"; ep >> input. Stream compatible.
- Optional everything - optional service names
- IP options - rarely used, but would be nice to have (long fat pipe)
- readfrom/sendto - with null sockaddr by default?
- readv, writev, recvmsg, sendmsg - perhaps
- IPv6 raw sockets - no such thing
- Datalink access - could use libpcap but not socket interface portably
- Out-of-band data/urgent data for TCP - rarely used
- Application-layer protocols - belong in other classes, but todo
- Non-blocking I/O - not very efficient, existed in earlier versions but was taken out
- Signal-driven I/O - blah
- select and poll - hows this fit in?
- Unix Domain Sockets - although useful, not completely portable (Win32)
- Routing Sockets - no datalink access yet so can't be done, belongs in app
- Broadcast
- Multicast - I like it, should perhaps be implemented, but not much support
- threading - belongs in client app
- XTI - never

# Endpoint Class

This class implements a "socket", a single endpoint connected to another endpoint. Member variables m_remote and m_local represent these; they are of type EndpointAddrinfo.

## Constructors

- Endpoint::Endpoint(int type, EndpointAddrlist addr)
- Endpoint::Endpoint(int type, string hostname, string service = "")
- Endpoint::Endpoint(int type, EndpointAddrlist remote, EndpointAddrlist local)
- Endpoint::Endpoint(int type, string remotehost, string remoteservice, string localhost, string localservice)

The one-address constructors interpret the address as local if `type` specifies a server, remote if client -- and then calls the two-address constructor. The string parameters just create `EndpointAddrlist`s and pass them to the others. Each constructor is implemented as a `Create` method, the real constructor simply calls this. Notice how address lists as opposed to a single address are passed: if the first one fails, the others are tried; m_local and m_remote are set to the connected `EndpointAddress`es.

### int type

Specifies protocol and client/server, see address.html.

### string hostname

See address.html. For clients, this is the remote address, for servers, this is the local address.

### string service

Default service, see above.

## operator string()

Returns the socket pair as a string, for example: "127.0.0.1:8000 <--> 127.0.0.1:3402". The local address is shown first followed by the foreign address. Invalid addresses are shown as "(invalid)".

## operator bool()

Returns true if is connected (m_bool member variable). More useful with TCP sockets than UDP sockets. connect() rarely fails with UDP sockets; you'll usually be notified of a UDP port being closed when you try to write to it. If you want to make sure, write a 0-byte packet and abort if it fails. Endpoint doesn't do this for you because that might interfere with the data.

## bool Write(string)

Writes all data in string, looping if necessary. Calls send(). If any of the send() calls returns -1, returns false. This means the remote host closed the connection, and if you try to send more you'll cause a SIGPIPE on Unix.

## std::string Stats()

Return a string of various statistics of the socket usage. You can also call the socket-wide `GetBytesRecv()`, `GetBytesSent()`, or application-wide `GetAllBytesRecv()` and `GetAllBytesSent()` calls individually.

## int m_error_code; std::string m_error_str

Error codes and error strings. Check these if !ep (m_bool=false). Defined values for `m_error_code` are EP_ERROR_NONE, EP_ERROR_SOCKET, EP_ERROR_BIND, EP_ERROR_ACCEPT, EP_ERROR_SETSOCKOPT, EP_ERROR_CONNECT, EP_ERROR_ADDRESS, and the EndpointAddrlist error EP_ERROR_GETADDRINFO. Each code corresponds to the system call where an error occured. `m_error_str` is a descriptive, human readable string of the error, suitable for printing. If Endpoint attempts to create an EndpointAddrlist and fails, the error will propagate into these variables.

## static int set_raw_sockfd(int fd)

Set the socket descriptor `g_raw_sockfd` used for raw sockets, to fd. Useful for, on Unix, separating the `socket()` call (which usually has to run as root) with the rest of the application code.

## static void Initialize()

Initialize the socket library. Necessary on Win32; this function is called upon the first instanciation of an Endpoint object. On other platforms, nothing happens.

# References

Endpoint isn't the only C++ class to utilize TCP/IP sockets, nor does it claim to be the best. Below are other C++ classes whose purpose is the same as or similar to that of Endpoint's, so one can learn from them.

Microsoft Foundation Classes' CSocket
  See CSocket Considered Harmful, problems with being asynchronous and synchronous

NMSTL's Socket
  Part of the "Networking, Messaging, Servers, and Threading Library", seems to be just a thin wrapper.

Jason But's SocketCC
  IPv4, IPv6, UDP, TCP, SocketException, IPAddress, several classes for TCP and UDP. No Win32 support, targetted at Linux.

ACE Sockets
  Not much information

Dr. Clue's Socket
  Looks comprehensive, but no Win32 support.

Rene Nyffenegger's Socket for Win32
  SocketServer, SocketSelect, UDP. Win32 (WinSock2) only

Socket++
  "Socket++ is a family of C++ classes that gives the same interface as the iostream classes for input and output for communication between processes.", has Internet socks as well as Unix domain, implements Echo and SMTP example "protocol" classes, no IPv6. RedHat, Debian, FreeBSD, WinSock(?). Wrappers provided for pipe(), socketpair(), popen() and fork(). GPL'd. "Socket++ is a iostream like C++ class library for UNIX and INET domains of sockets and protocols.".

libsocketcpp
  "Libsocketcpp provides a easy-to-use C++ class. With this class, TCP and UDP functionality can be added to any program quickly and easily." XXX

AdaSockets
- non-C++ (Ada)
  "AdaSockets allows Ada programmers to use sockets from within their programs with an easy-to-use Ada-friendly interface." XXX

Ruby/TCPSocketPipe - non-C++ (Ruby)
  "A Ruby library to create I/O pipes for TCP socket tunneling" XXX

The Endpoint Library
  An MFC, WinSock 1.1 socket library from 1997. Not to be confused with the Endpoint C++ Socket Library.
  - Unix Network Programming - a must
  - Beej's Guide to Network Programming - an excellent tutorial, good overview
  - BSD Sockets: A Quick And Dirty Primer

    # Frequently Asked Questions

    ## On Win32, where is the inet_ntop function?

    WinSock is missing this function. The implementation from BIND is included in `inet_ntop.c`. You can link to `inet_ntop_ipv4.c` if you only want IPv4 and want to save a little space, but in general `inet_ntop.c` is preferred. Add this file to your project if you get an `error LNK2001: unresolved external symbol _inet_ntop`.

    ## On Win32, I get an error saying `getaddrinfo` or `addrinfo` is not found, what can I do?

    You need to download the core "Microsoft Platform SDK" which includes this function. Ask Google for where to download this. Copy the files from "include" to your Microsoft Visual Studio "include" directory, overwriting them. The compile should now work.

    ## On Win32, I get tons of link errors, how do I fix it?

    You need to link with `ws2_32.lib`, and the object files of `endpoint.cpp`, `address.cpp`, and `inet_ntop.c`. Also link to `ws2_32.lib` under Project -> Settings -> Link -> General -> Object/library modules.

    ## On Win32, should I include support for "Windows Sockets" in the MFC AppWizard?

    Unfortunately, no, as the afxsock.h header will conflict with Endpoint. If you created a project with WOSA support, you can fix it by removing #include <afxsock.h> from stdafx.h and replacing AfxSocketInit() with Endpoint::Initialize(). Also, you may have to change the precompiled header option (Project -> Settings -> C++ -> Category=Precompiled Headers) from "Use precompiled header file (.pch" to "Automatic use of precompiled headers" through stdafx.h. Endpoint doesn't include stdafx.h.

    ## On Win32, I get `fatal error C1189: #error : WINDOWS.H already included. MFC apps must not #include <windows.h>`.

    Include endpoint.h in stdafx.h, after the normal afx includes.

    ## Are raw sockets supported on Win32?

    Yes, provided your version supports it (Windows XP or Windows 2000). You may be able to create raw sockets as normal users.

    # About the Author

    Jeff Connelly. Comments, questions, and criticism welcome.

    Happy hacking!