socket_server_pos.cpp
Go to the documentation of this file.
1 
9 /*****************************************************************************
10 ** Cross platform
11 *****************************************************************************/
12 
13 #include <ecl/config/ecl.hpp>
14 #ifndef ECL_IS_APPLE
15 #ifdef ECL_IS_POSIX
16 
17 /*****************************************************************************
18 ** Includes
19 *****************************************************************************/
20 
21 #include <unistd.h>
23 #include "../../include/ecl/devices/socket_connection_status.hpp"
24 #include "../../include/ecl/devices/socket_server_pos.hpp"
25 
26 /*****************************************************************************
27 ** Namespaces
28 *****************************************************************************/
29 
30 namespace ecl {
31 
32 /*****************************************************************************
33 ** Implementation [SocketServer]
34 *****************************************************************************/
35 
36 SocketServer::SocketServer(const unsigned int &port_number) :
37  port(port_number),
38  is_open(false),
39  error_handler(NoError)
40 {
41  ecl_try {
42  open(port_number);
43  } ecl_catch ( const StandardException &e ) {
44  ecl_throw(StandardException(LOC,e));
45  }
46 }
47 
48 bool SocketServer::open( const unsigned int& port_number ) {
49 
50  if ( this->open() ) { this->close(); }
51  port = port_number;
52 
53  /*************************************************************************
54  * Open socket
55  *************************************************************************
56  * PF_INET (IP4), PF_LOCAL (LOCALHOST)
57  * SOCK_STREAM (TCPIP), SOCK_DGRAM (UDP), SOCK_RAW
58  * Last argument is generally always 0 (sub-type)
59  */
60  socket_fd = socket(AF_INET, SOCK_STREAM, 0);
61 // socket_fd = socket(PF_INET, SOCK_STREAM, 0);
62  if ( socket_fd == -1 ) {
63  ecl_throw(devices::socket_exception(LOC));
64  error_handler = devices::socket_error();
65  return false;
66  }
67 
68  /*************************************************************************
69  * Configure Socket Details
70  ************************************************************************/
71  // allow *immediate* socket reuse, http://www.ibm.com/developerworks/library/l-sockpit/
72  int ret, on;
73  on = 1;
74  ret = setsockopt( socket_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) );
75  // other options
76  struct sockaddr_in server;
77  server.sin_family = AF_INET; // host byte order
78  server.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP
79  server.sin_port = htons(port); // short host byte order to network byte order
80  memset(server.sin_zero, '\0', sizeof server.sin_zero); // zero the server structure
81 
82  /*************************************************************************
83  * Bind address to the socket
84  ************************************************************************/
85  int bind_result = bind(socket_fd, (struct sockaddr *) &server, sizeof(server));
86  if ( bind_result == - 1 ) {
87  is_open = true;
88  ecl_throw(devices::bind_exception(LOC));
89  error_handler = devices::bind_error();
90  return false;
91  }
92  is_open = true;
93  error_handler = NoError;
94  return true;
95 }
96 
97 int SocketServer::listen() {
98 
99  /*********************
100  ** Params
101  **********************/
102  ::listen(socket_fd,1); // Number of clients to allow
103 
104  /*********************
105  ** Listen
106  **********************/
107  struct sockaddr_in client;
108  int client_length = sizeof(client);
109 
110  client_socket_fd = accept(socket_fd, (struct sockaddr *) &client, (socklen_t *) &client_length);
111  if (client_socket_fd < 0) {
112  ecl_throw(devices::accept_exception(LOC));
113  error_handler =devices::accept_error();
114  return -1;
115  }
116  error_handler = NoError;
117  return client_socket_fd;
118 
119 }
120 
121 /*****************************************************************************
122 ** Implementation [SocketServer][Source]
123 *****************************************************************************/
124 
125 long SocketServer::read(char *s, const unsigned long &n) {
126 
127  if ( !open() ) { return ConnectionDisconnected; }
128 
129  int bytes_read = ::recv(client_socket_fd, s, n, 0);
130  if ( bytes_read < 0 ) {
131  ecl_debug_throw(devices::receive_exception(LOC));
132  error_handler = devices::receive_error();
133  return ConnectionProblem;
134  }
135 
136  if ( bytes_read == 0 ) {
137  // Server has dropped
138  close();
139  return ConnectionHungUp;
140  }
141  error_handler = NoError;
142  return bytes_read;
143 }
144 
145 long SocketServer::peek(char *s, const unsigned long &n) {
146 
147  int bytes_read = ::recv(client_socket_fd, s, n, MSG_PEEK);
148  if ( bytes_read < 0 ) {
149  ecl_debug_throw(devices::receive_exception(LOC));
150  error_handler = devices::receive_error();
151  return ConnectionProblem;
152  }
153  error_handler = NoError;
154  return bytes_read;
155 };
156 
157 long SocketServer::remaining() {
158  unsigned long bytes;
159  int result = ioctl(client_socket_fd, FIONREAD, &bytes);
160  if ( result == -1 ) {
161  ecl_debug_throw(devices::ioctl_exception(LOC));
162  error_handler = devices::ioctl_error();
163  return ConnectionProblem;
164  }
165  error_handler = NoError;
166  return bytes;
167 };
168 
169 
170 /*****************************************************************************
171 ** Implementation [SocketServer][Sink]
172 *****************************************************************************/
173 
174 long SocketServer::write(const char *s, unsigned long n) {
175  #ifdef MSG_NOSIGNAL
176  int bytes_written = ::send(client_socket_fd,s,n,0|MSG_NOSIGNAL);
177  #else
178  int bytes_written = ::send(client_socket_fd,s,n,0);
179  #endif
180  if ( bytes_written < 0 ) {
181  switch(errno) {
182  case ( EPIPE ) : {
183  close();
184  return ConnectionHungUp;
185  }
186  default : {
187  ecl_debug_throw( devices::send_exception(LOC) );
188  error_handler = devices::send_error();
189  return ConnectionProblem;
190  }
191  }
192  }
193  error_handler = NoError;
194  return bytes_written;
195 }
196 
197 } // namespace ecl
198 
199 #endif /* ECL_IS_POSIX */
200 #endif /* !ECL_IS_APPLE */
ecl::ConnectionHungUp
@ ConnectionHungUp
Used to signify when a server/client detects that the other end has 'hung up'.
Definition: socket_connection_status.hpp:49
ecl_try
#define ecl_try
ecl::ConnectionProblem
@ ConnectionProblem
Was some error in the last operation..
Definition: socket_connection_status.hpp:47
ecl::NoError
NoError
standard_exception.hpp
ecl_catch
#define ecl_catch(exception)
ecl_throw
#define ecl_throw(exception)
ecl
Embedded control libraries.
ecl::ConnectionDisconnected
@ ConnectionDisconnected
Used to state when a server/client detects that there is no other connection at the other end.
Definition: socket_connection_status.hpp:48
ecl_debug_throw
#define ecl_debug_throw(exception)


ecl_devices
Author(s): Daniel Stonier
autogenerated on Wed Mar 2 2022 00:16:45