Fawkes API  Fawkes Development Version
socket.h
00001 
00002 /***************************************************************************
00003  *  socket.h - Fawkes socket base class
00004  *
00005  *  Created: Thu Nov 09 12:55:25 2006
00006  *  Copyright  2006  Tim Niemueller [www.niemueller.de]
00007  *
00008  ****************************************************************************/
00009 
00010 /*  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version. A runtime exception applies to
00014  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU Library General Public License for more details.
00020  *
00021  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00022  */
00023 
00024 #ifndef __NETCOMM_SOCKET_SOCKET_H_
00025 #define __NETCOMM_SOCKET_SOCKET_H_
00026 
00027 #include <core/exception.h>
00028 #include <core/exceptions/software.h>
00029 
00030 #include <sys/socket.h>
00031 #include <sys/types.h>
00032 #include <netinet/in.h>
00033 // just to be safe nobody else can do it
00034 #include <sys/signal.h>
00035 
00036 #ifdef POLL_IN
00037 #  undef POLL_IN
00038 #endif
00039 #ifdef POLL_OUT
00040 #  undef POLL_OUT
00041 #endif
00042 #ifdef POLL_PRI
00043 #  undef POLL_PRI
00044 #endif
00045 #ifdef POLL_RDHUP
00046 #  undef POLL_RDHUP
00047 #endif
00048 #ifdef POLL_ERR
00049 #  undef POLL_ERR
00050 #endif
00051 #ifdef POLL_HUP
00052 #  undef POLL_HUP
00053 #endif
00054 
00055 
00056 namespace fawkes {
00057 
00058 class SocketException : public Exception
00059 {
00060  public:
00061   SocketException(const char *msg, int _errno);
00062   SocketException(const char *msg);
00063 };
00064 
00065 class Socket
00066 {
00067  public:
00068 
00069   static const short POLL_IN;
00070   static const short POLL_OUT;
00071   static const short POLL_PRI;
00072   static const short POLL_RDHUP;
00073   static const short POLL_ERR;
00074   static const short POLL_HUP;
00075   static const short POLL_NVAL;
00076 
00077   Socket(int domain, int type, int protocol, float timeout = 0.f);
00078   Socket(Socket &socket);
00079   virtual ~Socket();
00080 
00081   virtual void         connect(const char *hostname, const unsigned short int port);
00082   virtual void         connect(struct sockaddr *addr_port, unsigned int struct_size);
00083 
00084   virtual void         bind(const unsigned short int port);
00085   virtual void         bind(const unsigned short int port,
00086                             const char *hostname);
00087 
00088   virtual void         listen(int backlog = 1);
00089   virtual Socket *     accept();
00090   virtual void         close();
00091   virtual bool         available();
00092 
00093   virtual size_t       read(void *buf, size_t count, bool read_all = true);
00094   virtual void         write(const void *buf, size_t count);
00095   virtual void         send(void *buf, size_t buf_len);
00096   virtual void         send(void *buf, size_t buf_len,
00097                             const struct sockaddr *to_addr, socklen_t addr_len);
00098   virtual size_t       recv(void *buf, size_t buf_len);
00099   virtual size_t       recv(void *buf, size_t buf_len,
00100                             struct sockaddr *from_addr, socklen_t *addr_len);
00101 
00102   /** Clone socket.
00103    * This method has to be implemented by subclass to correctly clone the instance.
00104    * @return cloned socket
00105    */
00106   virtual Socket *     clone() = 0;
00107 
00108   virtual short        poll(int timeout = -1, short what = POLL_IN | POLL_HUP | POLL_PRI | POLL_RDHUP);
00109 
00110   virtual bool         listening();
00111 
00112   virtual unsigned int mtu();
00113 
00114   /** Accept connection.
00115    * This method works like accept() but it ensures that the returned socket is of
00116    * the given type.
00117    * @return socket to client
00118    */
00119   template <class SocketType>
00120     SocketType *     accept();
00121 
00122  protected:
00123   Socket();
00124 
00125   int sock_fd;
00126   float timeout;
00127   struct ::sockaddr_in  *client_addr;
00128   unsigned int         client_addr_len;
00129 
00130 };
00131 
00132 
00133 template <class SocketType>
00134 SocketType *
00135 Socket::accept()
00136 {
00137   Socket *s = accept();
00138   if (SocketType *ts = dynamic_cast<SocketType *>(s)) {
00139     return ts;
00140   } else {
00141     delete s;
00142     throw TypeMismatchException("Socket types do not match");
00143   }
00144 }
00145 
00146 } // end namespace fawkes
00147 
00148 #endif