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 
00034 namespace fawkes {
00035 
00036 class SocketException : public Exception
00037 {
00038  public:
00039   SocketException(const char *msg, int _errno);
00040   SocketException(const char *msg);
00041 };
00042 
00043 class Socket
00044 {
00045  public:
00046 
00047   static const short POLL_IN;
00048   static const short POLL_OUT;
00049   static const short POLL_PRI;
00050   static const short POLL_RDHUP;
00051   static const short POLL_ERR;
00052   static const short POLL_HUP;
00053   static const short POLL_NVAL;
00054 
00055   Socket(int domain, int type, int protocol, float timeout = 0.f);
00056   Socket(Socket &socket);
00057   virtual ~Socket();
00058 
00059   virtual void         connect(const char *hostname, const unsigned short int port);
00060   virtual void         connect(struct sockaddr *addr_port, unsigned int struct_size);
00061 
00062   virtual void         bind(const unsigned short int port);
00063   virtual void         bind(const unsigned short int port,
00064                             const char *hostname);
00065 
00066   virtual void         listen(int backlog = 1);
00067   virtual Socket *     accept();
00068   virtual void         close();
00069   virtual bool         available();
00070 
00071   virtual size_t       read(void *buf, size_t count, bool read_all = true);
00072   virtual void         write(const void *buf, size_t count);
00073   virtual void         send(void *buf, size_t buf_len);
00074   virtual void         send(void *buf, size_t buf_len,
00075                             const struct sockaddr *to_addr, socklen_t addr_len);
00076   virtual size_t       recv(void *buf, size_t buf_len);
00077   virtual size_t       recv(void *buf, size_t buf_len,
00078                             struct sockaddr *from_addr, socklen_t *addr_len);
00079 
00080   /** Clone socket.
00081    * This method has to be implemented by subclass to correctly clone the instance.
00082    * @return cloned socket
00083    */
00084   virtual Socket *     clone() = 0;
00085 
00086   virtual short        poll(int timeout = -1, short what = POLL_IN | POLL_HUP | POLL_PRI | POLL_RDHUP);
00087 
00088   virtual bool         listening();
00089 
00090   virtual unsigned int mtu();
00091 
00092   /** Accept connection.
00093    * This method works like accept() but it ensures that the returned socket is of
00094    * the given type.
00095    * @return socket to client
00096    */
00097   template <class SocketType>
00098     SocketType *     accept();
00099 
00100  protected:
00101   Socket();
00102 
00103   int sock_fd;
00104   float timeout;
00105   struct ::sockaddr_in  *client_addr;
00106   unsigned int         client_addr_len;
00107 
00108 };
00109 
00110 
00111 template <class SocketType>
00112 SocketType *
00113 Socket::accept()
00114 {
00115   Socket *s = accept();
00116   if (SocketType *ts = dynamic_cast<SocketType *>(s)) {
00117     return ts;
00118   } else {
00119     delete s;
00120     throw TypeMismatchException("Socket types do not match");
00121   }
00122 }
00123 
00124 } // end namespace fawkes
00125 
00126 #endif