/*
 *
 *
 *    socket.h
 *
 *    C++ header file for the following socket classes:
 *        socket
 *        datagram_socket
 *        stream_socket
 *
 *    and the following inner classes:
 *        socket::address
 *
 *    =========================================================================
 *
 *    Copyright (C) 2001-2003 by Matt Roberts, KK5JY.
 *
 *    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
 *
 *    =========================================================================
 *
 *
 */


#ifndef __SOCKET_H
#define __SOCKET_H

/* standard C++ includes */
#include <string>

/* clib includes */
#include <sys/types.h>
#include <sys/socket.h>

/* local library includes */
#include <my++/device.h>
#include <my++/exception.h>

	namespace my {

		/*
		 *
		 *
		 *    class socket
		 *    
		 *    Abstract base class for all socket objects.
		 *
		 *
		 */

		class socket {
			public:
				typedef exception_template<socket> exception;

				class address {
					public:
						/* override these to convert to/from socket address */
						virtual void to_sockaddr (sockaddr *sa) const = 0;
						virtual void from_sockaddr (const sockaddr *sa) = 0;

						/* override these to give users a pretty UI display for all addresses */
						virtual address & parse (const std::string &s) = 0;
						virtual std::string & to_string (std::string &s) const = 0;
						virtual std::string to_string (void) const = 0;
						virtual ~address (void) { /* noop */ };
				};

				virtual void bind (const address &a) = 0;
				virtual void bind (const std::string &a) = 0;
				virtual void name (address &a) = 0;
				virtual void ishutdown (void) = 0;
				virtual void oshutdown (void) = 0;
				virtual void ioshutdown (void) = 0;

				virtual ~socket (void) throw () { /* noop */ };
		};

		
		/*
		 *
		 *
		 *    class datagram_socket
		 *
		 *    Abstract base classes for datagram sockets.   This class defines the interface
		 *    for methods that are specific to stream sockets.
		 *
		 *
		 */

		class datagram_socket : public socket {
			public:
				virtual size_t get_from (address &a, unsigned char *b, size_t len) = 0;
				virtual size_t get_from (address &a, char *b, size_t len) = 0;
				virtual size_t get_from (address &a, void *b, size_t len) = 0;

				virtual size_t put_to (const address &a, const unsigned char *b, size_t len) = 0;
				virtual size_t put_to (const address &a, const char *b, size_t len) = 0;
				virtual size_t put_to (const address &a, const void *b, size_t len) = 0;

				~datagram_socket (void) throw() { /* noop */ };
		};


		/*
		 *
		 *
		 *    class stream_socket
		 *
		 *    Abstract base class for a stream socket.  This class defines the interface for
		 *    methods that are specific to stream sockets.
		 *
		 *
		 */

		class stream_socket : public socket, public iodevice {

			public:
				virtual void connect (const socket::address &a) = 0;
				virtual void connect (const std::string &a) = 0;
				virtual void listen (int backlog) = 0;
				virtual void listen (void) = 0;
				virtual void accept (socket &s, std::string &a) = 0;
				virtual void accept (socket &s, socket::address &a) = 0;
				virtual void accept (socket &s) = 0;
				virtual void peer (address &a) = 0;
				virtual void disconnect (void) = 0;

				virtual void close (void) throw() = 0;
				virtual void open (const std::string &name, const device::open_flags f) = 0;

				~stream_socket (void) throw() { /* noop */ };

		};

	}

#endif /* __SOCKET_H */
