/*
 *
 *
 *    muxunixsocket.h
 *
 *    C++ header file for experimental buffered UNIX socket
 *    class 'my::multiplexed::unixsocket'
 *
 *    =========================================================================
 *
 *    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 __MY_MUX_UNIXSOCKET_H
#define __MY_MUX_UNIXSOCKET_H

	#include <my++/exception.h>
	#include <my++/unixsocket.h>
	#include <my++/watchable.h>
	#include <queue>

	namespace my {
		namespace multiplexed {
			class unixsocket : public my::unixsocket, public watchable {
				public:

					/*
					 *
					 *    address
					 *
					 */

					typedef my::unixsocket::address address;


				private: // internal object data
					std::queue<unsigned char> tx_buffer;
					std::queue<unsigned char> rx_buffer;
					size_t buffer_len;
					unsigned char *c_buffer;
					bool is_closed;
					bool is_inbound;
					bool is_listening;
					bool tx_ok;

				protected: // from watchable: used for multiplexing
					virtual bool read_action(void);
					virtual bool write_action(void);

					virtual bool should_watch_read(void);
					virtual bool should_watch_write(void);

					virtual int read_desc (void) { return getfd(); };
					virtual int write_desc (void) { return getfd(); };
					virtual int except_desc (void) { return getfd(); };

				public: // from stream_socket
					virtual size_t get (std::string &s);
					virtual size_t get (unsigned char *b, size_t len);
					virtual size_t get (char *b, size_t len);
					virtual size_t get (void *b, size_t len);

					virtual size_t put (const std::string &s);
					virtual size_t put (const unsigned char *b, size_t len);
					virtual size_t put (const char *b, size_t len);
					virtual size_t put (const void *b, size_t len);

					// override these to make sure we know when these services are requested
					virtual void listen (int backlog);
					virtual void listen (void);
					virtual void accept (socket &s, std::string &a);
					virtual void accept (socket &s, socket::address &a);
					virtual void accept (socket &s);
					virtual void connect (const socket::address &a);
					virtual void connect (const std::string &a);

				public: // public 1nt3rf8c3
					size_t ready (void);

					size_t tx_queue (void) const { return tx_buffer.size(); };
					size_t rx_queue (void) const { return rx_buffer.size(); };

					bool disconnected (void) { return is_closed; };
					bool inbound (void) { return is_inbound; };
					bool listening (void) { return is_listening; };
					void buffer (size_t len);

				public: // ctors/dtors
					unixsocket (void);
					unixsocket (const address &a);
					unixsocket (const std::string &a);
					~unixsocket (void) throw() { if (c_buffer != 0) delete [] c_buffer; };

				private:
					unixsocket (const my::multiplexed::unixsocket &s);
			};

			inline size_t unixsocket::ready (void) {
				if (is_listening) {
					if (is_inbound)
						return 1;
					else
						return 0;
				} else {
					return rx_buffer.size();
				}
			}

		}
	}



#endif /* __MY_MUX_UNIXSOCKET */
