socket_server_pos.cpp
Go to the documentation of this file.
00001 
00009 /*****************************************************************************
00010 ** Cross platform
00011 *****************************************************************************/
00012 
00013 #include <ecl/config/ecl.hpp>
00014 #ifndef ECL_IS_APPLE
00015 #ifdef ECL_IS_POSIX
00016 
00017 /*****************************************************************************
00018 ** Includes
00019 *****************************************************************************/
00020 
00021 #include <unistd.h>
00022 #include <ecl/exceptions/standard_exception.hpp>
00023 #include "../../include/ecl/devices/socket_connection_status.hpp"
00024 #include "../../include/ecl/devices/socket_server_pos.hpp"
00025 
00026 /*****************************************************************************
00027 ** Namespaces
00028 *****************************************************************************/
00029 
00030 namespace ecl {
00031 
00032 /*****************************************************************************
00033 ** Implementation [SocketServer]
00034 *****************************************************************************/
00035 
00036 SocketServer::SocketServer(const unsigned int &port_number) ecl_throw_decl(StandardException) :
00037                 port(port_number),
00038                 is_open(false),
00039                 error_handler(NoError)
00040 {
00041     ecl_try {
00042         open(port_number);
00043     } ecl_catch ( const StandardException &e ) {
00044         ecl_throw(StandardException(LOC,e));
00045     }
00046 }
00047 
00048 bool SocketServer::open( const unsigned int& port_number ) ecl_throw_decl(StandardException) {
00049 
00050     if ( this->open() ) { this->close(); }
00051     port = port_number;
00052 
00053     /*************************************************************************
00054      * Open socket
00055      *************************************************************************
00056      * PF_INET (IP4), PF_LOCAL (LOCALHOST)
00057      * SOCK_STREAM (TCPIP), SOCK_DGRAM (UDP), SOCK_RAW
00058      * Last argument is generally always 0 (sub-type)
00059      */
00060     socket_fd = socket(AF_INET, SOCK_STREAM, 0);
00061 //    socket_fd = socket(PF_INET, SOCK_STREAM, 0);
00062     if ( socket_fd == -1 ) {
00063         ecl_throw(devices::socket_exception(LOC));
00064         error_handler = devices::socket_error();
00065         return false;
00066     }
00067 
00068     /*************************************************************************
00069      * Configure Socket Details
00070      ************************************************************************/
00071     // allow *immediate* socket reuse, http://www.ibm.com/developerworks/library/l-sockpit/
00072     int ret, on;
00073     on = 1;
00074     ret = setsockopt( socket_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) );
00075     // other options
00076     struct sockaddr_in server;
00077     server.sin_family = AF_INET;    // host byte order
00078     server.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP
00079     server.sin_port = htons(port);  // short host byte order to network byte order
00080     memset(server.sin_zero, '\0', sizeof server.sin_zero); // zero the server structure
00081 
00082     /*************************************************************************
00083      * Bind address to the socket
00084      ************************************************************************/
00085     int bind_result = bind(socket_fd, (struct sockaddr *) &server, sizeof(server));
00086     if ( bind_result == - 1 ) {
00087         is_open = true;
00088         ecl_throw(devices::bind_exception(LOC));
00089         error_handler = devices::bind_error();
00090         return false;
00091     }
00092     is_open = true;
00093     error_handler = NoError;
00094     return true;
00095 }
00096 
00097 int SocketServer::listen() ecl_throw_decl(StandardException) {
00098 
00099         /*********************
00100         ** Params
00101         **********************/
00102         ::listen(socket_fd,1); // Number of clients to allow
00103 
00104         /*********************
00105         ** Listen
00106         **********************/
00107     struct sockaddr_in client;
00108     int client_length = sizeof(client);
00109 
00110     client_socket_fd = accept(socket_fd, (struct sockaddr *) &client, (socklen_t *) &client_length);
00111     if (client_socket_fd < 0) {
00112         ecl_throw(devices::accept_exception(LOC));
00113         error_handler =devices::accept_error();
00114         return -1;
00115     }
00116     error_handler = NoError;
00117     return client_socket_fd;
00118 
00119 }
00120 
00121 /*****************************************************************************
00122 ** Implementation [SocketServer][Source]
00123 *****************************************************************************/
00124 
00125 long SocketServer::read(char *s, const unsigned long &n) ecl_debug_throw_decl(StandardException) {
00126 
00127     if ( !open() ) { return ConnectionDisconnected; }
00128 
00129     int bytes_read = ::recv(client_socket_fd, s, n, 0);
00130     if ( bytes_read < 0 ) {
00131         ecl_debug_throw(devices::receive_exception(LOC));
00132         error_handler = devices::receive_error();
00133         return ConnectionProblem;
00134     }
00135 
00136     if ( bytes_read == 0 ) {
00137         // Server has dropped
00138         close();
00139         return ConnectionHungUp;
00140     }
00141     error_handler = NoError;
00142     return bytes_read;
00143 }
00144 
00145 long SocketServer::peek(char *s, const unsigned long &n) ecl_debug_throw_decl(StandardException) {
00146 
00147         int bytes_read = ::recv(client_socket_fd, s, n, MSG_PEEK);
00148     if ( bytes_read < 0 ) {
00149         ecl_debug_throw(devices::receive_exception(LOC));
00150         error_handler = devices::receive_error();
00151         return ConnectionProblem;
00152     }
00153     error_handler = NoError;
00154     return bytes_read;
00155 };
00156 
00157 long SocketServer::remaining() {
00158     unsigned long bytes;
00159     int result = ioctl(client_socket_fd, FIONREAD, &bytes);
00160     if ( result == -1 ) {
00161         ecl_debug_throw(devices::ioctl_exception(LOC));
00162         error_handler = devices::ioctl_error();
00163         return ConnectionProblem;
00164     }
00165     error_handler = NoError;
00166     return bytes;
00167 };
00168 
00169 
00170 /*****************************************************************************
00171 ** Implementation [SocketServer][Sink]
00172 *****************************************************************************/
00173 
00174 long SocketServer::write(const char *s, unsigned long n) ecl_debug_throw_decl(StandardException) {
00175     #ifdef MSG_NOSIGNAL
00176         int bytes_written = ::send(client_socket_fd,s,n,0|MSG_NOSIGNAL);
00177     #else
00178         int bytes_written = ::send(client_socket_fd,s,n,0);
00179     #endif
00180     if ( bytes_written < 0 ) {
00181         switch(errno) {
00182             case ( EPIPE ) : {
00183                 close();
00184                 return ConnectionHungUp;
00185             }
00186             default : {
00187                     ecl_debug_throw( devices::send_exception(LOC) );
00188                     error_handler = devices::send_error();
00189                     return ConnectionProblem;
00190             }
00191         }
00192     }
00193     error_handler = NoError;
00194     return bytes_written;
00195 }
00196 
00197 } // namespace ecl
00198 
00199 #endif /* ECL_IS_POSIX */
00200 #endif  /* !ECL_IS_APPLE */


ecl_devices
Author(s): Daniel Stonier
autogenerated on Thu Jun 6 2019 21:18:03