00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #if !defined EC_SOCKET_HPP
00024 #define EC_SOCKET_HPP
00025
00026
00027
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
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;
00194 temp.sin_port = htons(port_no);
00195 temp.sin_addr.s_addr = INADDR_ANY;
00196 bzero(&(temp.sin_zero), 8);
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