Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

socket.hpp

Go to the documentation of this file.
00001 /*
00002  * Equation Cruncher
00003  * Copyright (C) 2004  Dhruv Matani(dhruvbird@yahoo.com)
00004  * 
00005  * 
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License as
00008  * published by the Free Software Foundation; either version 2 of the
00009  * License, or (at your option) any later version.
00010  * 
00011  * This program is distributed in the hope that it will be useful, but
00012  * WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * General Public License for more details.
00015  * 
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00019  * USA
00020  */
00021 
00022 
00023 #if !defined EC_SOCKET_HPP
00024 #define EC_SOCKET_HPP
00025 
00026 
00027 // Standard UNIX headers.
00028 #include <sys/types.h> 
00029 #include <netinet/in.h> 
00030 #include <arpa/inet.h>
00031 #include <sys/socket.h> 
00032 #include <sys/wait.h>
00033 #include <unistd.h>
00034 #include <netdb.h>
00035 
00036 // Standard C++ headers.
00037 #include <cstdlib>
00038 #include <cstring>
00039 #include <cerrno>
00040 #include <exception>
00041 #include <stdexcept>
00042 #include <sstream>
00043 #include <string>
00044 #include <assert.h>
00045 
00058 namespace eqn_cruncher
00059 {
00071   class socket_error : public std::runtime_error
00072   {
00073   public:
00080     socket_error(std::string const& _reason)
00081       : std::runtime_error(_reason)
00082     { }
00083 
00084 
00088     socket_error()
00089       : std::runtime_error("socket_error")
00090     { }
00091   };
00092 
00093 
00100   class host_error : public socket_error
00101   {
00102   public:
00109     host_error(std::string const& _reason)
00110       : socket_error(_reason)
00111     { }
00112 
00116     host_error()
00117       : socket_error("host_error")
00118     { }
00119   };
00120 
00121 
00130   class port_error : public socket_error
00131   {
00132   public:
00139     port_error(std::string const& _reason)
00140       : socket_error(_reason)
00141     { }
00142 
00143 
00147     port_error()
00148       : socket_error("port_error")
00149     { }
00150   };
00151 
00152 
00159   class socket
00160   {
00161     int sock_id;
00162 
00163   public:
00168     typedef std::pair<sockaddr_in, int> accept_t;
00169 
00175     int
00176     get_sockid() { return this->sock_id; }
00177 
00178 
00188     static
00189     sockaddr_in
00190     get_socket_info(unsigned short int port_no)
00191     {
00192       sockaddr_in temp;
00193       temp.sin_family = AF_INET;          // host byte order.
00194       temp.sin_port = htons(port_no);     // short, network byte order.
00195       temp.sin_addr.s_addr = INADDR_ANY;  // auto-fill with my IP.
00196       bzero(&(temp.sin_zero), 8);         // zero the rest of the struct.
00197       return temp;
00198     }
00199 
00200 
00208     static
00209     hostent*
00210     host_by_name(std::string const& host_name)
00211     {
00212       hostent* temp = gethostbyname(host_name.c_str());
00213       if (temp == NULL)
00214         throw host_error("Error looking up Host Name...");
00215       return temp;
00216     }
00217 
00218 
00227     static
00228     std::string
00229     str_ip(unsigned int uint_ip)
00230     {
00231       typedef unsigned int uint;
00232       uint mask = 255;
00233       mask <<= 24;
00234       std::ostringstream os;
00235       os<<((uint_ip & mask)>>24)<<'.';
00236       mask >>= 8;
00237       os<<((uint_ip & mask)>>16)<<'.';
00238       mask >>= 8;
00239       os<<((uint_ip & mask)>>8)<<'.';
00240       mask >>= 8;
00241       os<<(uint_ip & mask);
00242       return os.str();
00243     }
00244 
00245 
00252     socket() : sock_id(0)
00253     {
00254       sock_id = ::socket(AF_INET, SOCK_STREAM, 0);
00255       if (sock_id == -1)
00256         throw socket_error("Error creating socket!");
00257     }
00258 
00259 
00269     explicit
00270     socket(const int _sockid)
00271     {
00272       assert(_sockid != -1);
00273       sock_id = _sockid;
00274     }
00275 
00276 
00277     std::string
00278     get_remote_name()
00279     {
00280       sockaddr_in temp;
00281       socklen_t tsize = sizeof(sockaddr_in);
00282       ::getpeername(this->sock_id, reinterpret_cast<sockaddr*>(&temp), &tsize);
00283       return str_ip(ntohl(temp.sin_addr.s_addr));
00284     }
00285 
00286 
00291     void
00292     reuse_sock_addr()
00293     {
00294       volatile int opts = 1;
00295       ::setsockopt(this->sock_id, SOL_SOCKET, SO_REUSEADDR, 
00296                    (void*)&opts, sizeof(opts));
00297     }
00298 
00299 
00305     void
00306     bind(unsigned short int _pno)
00307     {
00308       sockaddr_in temp = get_socket_info(_pno);
00309       if (::bind(sock_id, reinterpret_cast<sockaddr*>(&temp), sizeof(sockaddr)) == -1)
00310         {
00311           std::ostringstream port_str;
00312           port_str<<_pno;
00313           throw port_error("Error Binding to Port: " + port_str.str());
00314         }
00315     }
00316 
00317 
00330     void
00331     connect(unsigned short int _pno, std::string const& host_name)
00332     {
00333       sockaddr_in temp = get_socket_info(_pno);
00334       hostent* thost = host_by_name(host_name);
00335 
00336       memcpy(&temp.sin_addr, thost->h_addr, thost->h_length);
00337 
00338       if (::connect(sock_id, reinterpret_cast<sockaddr*>(&temp), sizeof(sockaddr)) == -1)
00339         throw socket_error("Error Connecting to Host: " + host_name);
00340     }
00341 
00342 
00350     void
00351     listen(int max_queued = 10)
00352     {
00353       if (::listen(sock_id, max_queued) == -1)
00354         throw socket_error("Error while listening on Socket!");
00355     }
00356 
00357 
00362     accept_t
00363     accept()
00364     {
00365       sockaddr_in temp;
00366       int ret_size = sizeof(sockaddr_in);
00367       int new_sock_id = ::accept(sock_id, reinterpret_cast<sockaddr*>(&temp), 
00368                                  reinterpret_cast<socklen_t*>(&ret_size));
00369       if (new_sock_id == -1)
00370         throw socket_error("Error accepting Connection!");
00371 
00372       return std::make_pair(temp, new_sock_id);
00373     }
00374 
00375 
00387     int
00388     send(const char* buff, int buff_len)
00389     {
00390       int bytes_sent = 
00391         ::send(sock_id, buff, buff_len, 0);
00392 
00393       if (bytes_sent == -1)
00394         throw socket_error("Send Error!");
00395       return bytes_sent;
00396     }
00397 
00398 
00407     int
00408     send(std::string const& data)
00409     {
00410       return this->send(data.data(), data.size());
00411     }
00412 
00413 
00430     int
00431     sendto(const char* buff, int len, std::string const& host_name)
00432     {
00433       sockaddr_in temp = get_socket_info(0);
00434       temp.sin_addr = *(reinterpret_cast<in_addr*>(host_by_name(host_name)->h_addr));
00435 
00436       int bytes_sent = 
00437         ::sendto(sock_id, buff, len, 0, reinterpret_cast<sockaddr*>(&temp), 
00438                  sizeof(sockaddr));
00439       if (bytes_sent == -1)
00440         throw socket_error("SendTo Error!");
00441 
00442       return bytes_sent;
00443     }
00444 
00445 
00459     int
00460     sendto(std::string const& msg, std::string const& host_name)
00461     {
00462       return this->sendto(msg.data(), msg.size(), host_name);
00463     }
00464 
00465 
00477     int
00478     receive(void* buff, int buff_size)
00479     {
00480       int retval = ::recv(sock_id, buff, buff_size, 0);
00481       if (retval == -1)
00482         throw socket_error("Error Receiving data!");
00483       return retval;
00484     }
00485 
00486 
00499     int
00500     receive_from(void* buff, int buff_size)
00501     {
00502       sockaddr temp;
00503       socklen_t temp_len = sizeof(temp);
00504       int retval = 
00505         ::recvfrom(sock_id, buff, buff_size, 0, &temp, &temp_len);
00506       if (retval == -1)
00507         throw socket_error("Error Receiving data!");
00508       return retval;
00509     }
00510 
00511 
00515     void
00516     close()
00517     {
00518       ::shutdown(sock_id, SHUT_RDWR);
00519     }
00520   };
00521 }
00522 
00523 #endif // EC_SOCKET_HPP

Generated on Mon Oct 11 13:09:26 2004 for Equation Cruncher by doxygen1.2.18