libassa 3.5.1
Loading...
Searching...
No Matches
IPv4Socket.cpp
Go to the documentation of this file.
1// -*- c++ -*-
2//------------------------------------------------------------------------------
3// IPv4Socket.cpp
4//------------------------------------------------------------------------------
5// Copyright (C) 1997-2002 Vladislav Grinchenko
6//
7// This library is free software; you can redistribute it and/or
8// modify it under the terms of the GNU Library General Public
9// License as published by the Free Software Foundation; either
10// version 2 of the License, or (at your option) any later version.
11//------------------------------------------------------------------------------
12//
13#if defined(WIN32)
14# include <errno.h>
15# include <ws2tcpip.h>
16#else
17# include <sys/errno.h>
18#endif
19
20#include "assa/MemDump.h"
21#include "assa/IPv4Socket.h"
22
23using namespace ASSA;
24
28{
29 trace_with_mask("IPv4Socket::rdbuf(sb_)",SOCKTRACE);
30
31 if (sb_ == 0 || sb_ == m_rdbuf) {
32 return (sb_);
33 }
35 m_rdbuf = sb_;
36 return (old);
37}
38
39
40bool
42open (const int domain_)
43{
44 trace_with_mask("IPv4Socket::open",SOCKTRACE);
45
47
49
50 if (!is_valid_handler (m_fd)) {
51 EL((ASSAERR,"OS::socket() error: m_fd = %d\n", m_fd));
54 return (false);
55 }
56 DL ((SOCK,"domain = %d, m_fd = %d\n", domain_, m_fd));
57
58 clear ();
60
61 return (true);
62}
63
64bool
66close()
67{
68 trace_with_mask("IPv4Socket::close()",SOCKTRACE);
69
70 if (is_valid_handler (m_fd)) {
71 DL((SOCK,"Closed FD: %d\n",m_fd));
72
73 /*--- Flush data in output stream buffer ---*/
74 flush ();
77
78 /*---
79 Socket can be re-opened in the future.
80 If there is some bytes left in it since last read(2),
81 clean them up.
82 ---*/
83
84 if (m_rdbuf && m_rdbuf->in_avail ()) {
85 for (int c; (c=m_rdbuf->sbumpc ()) != EOF;) { }
86 }
87 }
88 return (true);
89}
90
91bool
94{
95 trace_with_mask("IPv4Socket::connect()",SOCKTRACE);
96
97 if (!is_valid_handler (m_fd) && open (getDomain()) == false) {
98 return false;
99 }
100
101 int ret = ::connect (m_fd,
102 (SA*) his_address_.getAddress(),
103 his_address_.getLength());
104 if (ret < 0)
105 {
106 int e = get_errno (); // is ASYNC connect in progress?
107 if (e == EINPROGRESS || e == EWOULDBLOCK) {
108 DL((SOCK,"FD: %d OS::connect() error\n",m_fd));
109 }
110 else {
111 EL((SOCK,"FD: %d OS::connect() error\n",m_fd));
112 }
113 return (false);
114 }
115
116 clear ();
117
118 DL((SOCK,"Connection opened on FD: %d\n", m_fd));
119 return (true);
120}
121
122bool
124bind (const Address& addr_)
125{
126 trace_with_mask("IPv4Socket::bind",SOCKTRACE);
127
128#if !defined(WIN32)
132 if ( getDomain() == AF_UNIX ) {
133 char* p = ((SA_UN *) addr_.getAddress())->sun_path;
134 m_path = new char[strlen(p)+1];
135 strcpy(m_path, p);
136 struct stat sb;
137
138 if (stat (m_path, &sb) == 0) {
139 if ( S_ISSOCK(sb.st_mode) || S_ISFIFO(sb.st_mode) ) {
140 unlink(m_path);
141 }
142 }
143 }
144#endif
145
146 /*---
147 From Stevens, Ch 7.5 (p.196):
148 "Set the SO_REUSEADDR socket option before calling bind(2)
149 in all TCP servers."
150 ---*/
152
153 int rt = ::bind(m_fd, addr_.getAddress(), addr_.getLength());
154
155 if ( rt < 0) {
156 EL((SOCK,"::bind() FD: %d failed\n",m_fd));
158 return (false);
159 }
160 Assure_return ( (::listen(m_fd, 5) == 0) );
161 return (true);
162}
163
177accept ()
178{
179 trace_with_mask("IPv4Socket::accept",SOCKTRACE);
180
181 socklen_t length = 0;
184
186
187 if ( getDomain() == AF_UNIX ) {
188 length = sizeof(struct sockaddr_in);
189 remote_address = (SA*) new SA_IN;
190 }
191 else /* AF_INET */
192 {
193 remote_address = (SA*) new SA_UN;
194 length = sizeof(struct sockaddr_un);
195 }
196 memset(remote_address, 0, length);
197
198#if !defined (_CYGWIN32__)
199 new_fd = ::accept(m_fd, remote_address, &length);
200#else
201 new_fd = ::accept(m_fd, remote_address, (int*)&length);
202#endif
203
204 if (!is_valid_handler (new_fd)) {
205 EL((ASSAERR,"::accept() failed (new_fd=%d)\n", new_fd));
206 close();
207 return NULL;
208 }
209 if (length == sizeof(SA_IN)) {
211
212 DL((SOCK,"Accepted new TCP connection from Addr %s, port %d\n",
213 inet_ntoa(sa_in->sin_addr), ntohs( sa_in->sin_port)));
214 }
215 else {
216#if !defined(WIN32)
218 DL((SOCK,"Accepted new UNIX connection from %s\n", sa_un->sun_path));
219#endif
220 }
221 delete remote_address;
222
223 IPv4Socket* s = new IPv4Socket (new_fd);
224 s->clear ();
225 s->turnOptionOn (Socket::nonblocking);
226 return s;
227}
228
229int
231read (char* packet_, const unsigned int size_)
232{
233 trace_with_mask("IPv4Socket::read",SOCKTRACE);
234
235 register int len;
236 register int sz = size_;
237 char* tmp = packet_;
238
239 if (!is_valid_handler (m_fd) < 0) {
240 return -1;
241 }
242
243 len = 0;
244 if (m_rdbuf->unbuffered ()) {
245 /*
246 --- This needs to be redesigned ---
247 I should read a character at a time in loop,
248 until I get all characters, or EWOULDBLOCK or EOF.
249 If ::read() returns 0 or -1, it will be converted
250 by sbumpc() into EOF. Otherwise, sbumpc() returns
251 character read. Is this the right thing here to do?
252 */
253 if ((len = m_rdbuf->sbumpc ()) >= 0) {
254 *tmp = len;
255 len = 1;
256 }
257 }
258 else {
259 len = m_rdbuf->sgetn (tmp, sz);
260 }
261 if (len == -1)
262 {
265 if (get_errno () != EWOULDBLOCK) {
266 EL((ASSAERR,"::read (fd=%d) failed.\n",m_fd));
268 }
269 return len;
270 }
271 tmp += len;
272 sz -= len;
273
274 if ((size_ - sz) == 0)
275 {
276 DL((SOCK,"Peer has dropped connection FD: %d\n",m_fd));
278 return 0;
279 }
280
281 DL((SOCKTRACE,"==> FD: %d Received %d bytes\n", m_fd, size_ - sz));
282 MemDump::dump_to_log (SOCKTRACE, "Data received:", packet_, size_ - sz);
283
284 /*
285 Return number of bytes read. If all requested bytes have been
286 read, then sz is 0 and size_ is returned. If sz != 0, then
287 writer has sent us a partial packet.
288 */
289 return (size_ - sz);
290}
291
292int
294write(const char* packet_, const unsigned int size_)
295{
296 trace_with_mask("IPv4Socket::write()",SOCKTRACE);
297
298 int ret = 0;
299
300 if (!is_valid_handler (m_fd)) {
301 return -1;
302 }
303
304 if (m_rdbuf->unbuffered ())
305 {
306 int wlen = size_;
307 char* p = (char*) packet_;
308
309 while (wlen-- > 0) {
310 if (m_rdbuf->sputc (*p++) == EOF) {
311 return (EOF);
312 }
313 }
314 ret = p - packet_;
315 }
316 else {
317 ret = m_rdbuf->sputn ((char*) packet_, size_);
318 }
319
320 if (ret > 0) {
321 DL((SOCK,"<= FD: %d Wrote %d bytes (requested %d bytes)\n",
322 m_fd, ret, size_));
323 MemDump::dump_to_log (SOCK, "Data written", (char*)packet_, ret);
324 }
325 return ret;
326}
327
330clone () const
331{
332 const char self[] = "IPv4Socket::clone";
334
335 handler_t nfd = dup (m_fd);
336 IPv4Socket* s = new IPv4Socket (nfd);
337
338 DL((SOCK,"Original socket has %d bytes in its get_area\n",
339 m_rdbuf->in_avail ()));
340
341 if (!is_valid_handler (nfd) || !good ()) {
342 s->setstate (Socket::failbit);
343 }
344 else {
345 s->clear ();
346 }
347
348 return s;
349}
350
351
#define Assure_return(exp_)
Test condition and return bool from a function if assertion fails.
Definition Assure.h:64
Class IPv4Socket covers domain types AF_INET and AF_UNIX.
#define EL(X)
A macro for writing error message to the Logger.
Definition Logger.h:285
#define DL(X)
A macro for writing debug message to the Logger.
Definition Logger.h:273
#define trace_with_mask(s, m)
trace_with_mask() is used to trace function call chain in C++ program.
Definition Logger.h:437
A Hex/Ascii memory dump of similar to od(1) UNIX utility.
A wrapper class to provide AutoPtr with reference semantics.
Definition AutoPtr.h:32
IPv4Socket * accept()
Accept connection on the listening socket.
int write(const char *buf_, const unsigned int size_)
Perform blocking write by writing packet of specified size.
IPv4Socket()
Default constructor.
Definition IPv4Socket.h:32
IPv4Socket * clone() const
"Virtual constructor".
virtual Streambuf * rdbuf()
Return a pointer to the Socketbuf associated with the stream.
Definition IPv4Socket.h:146
bool close()
Close socket connection.
bool connect(const Address &address_)
Client makes connection with the server at address_.
bool open(const int domain_)
Create socket.
Streambuf * m_rdbuf
Socketbuf.
Definition IPv4Socket.h:176
virtual bool bind(const Address &my_address_)
Server binds listening socket to its local well-known port.
const int getDomain() const
Get socket domain type.
Definition IPv4Socket.h:138
int read(char *buf_, const unsigned int size_)
Read packet of specified size and save it to the given buffer.
char * m_path
Path of UNIX domain socket.
Definition IPv4Socket.h:173
static void dump_to_log(unsigned long mask_, const char *info_, const char *msg_, int len_)
Write hex/ascii dump of a memory region to log file.
Definition MemDump.cpp:111
int m_type
Socket domain type.
Definition Socket.h:488
void setstate(iostate flag_)
Set socket state to flag_ by adding flag_ to the existing state.
Definition Socket.h:577
static void close_handler(handler_t &socket_)
Close socket endpoint in a portable way.
Definition Socket.h:448
bool turnOptionOn(opt_t opt_)
Enable socket option.
Definition Socket.cpp:185
@ reuseaddr
Allow local address reuse.
Definition Socket.h:100
@ nonblocking
Set Socket to a non-blocking mode (O_RDWR|O_NONBLOCK).
Definition Socket.h:115
handler_t m_fd
File descriptor.
Definition Socket.h:485
bool good() const
Indicates no error on the socket.
Definition Socket.h:315
void clear(iostate state_=Socket::goodbit)
Clear the socket state. Closed socket remains in bad state.
Definition Socket.h:571
virtual Socket & flush()
This function simply calls the public "synchronizing" function rdbuf()->pubsync() (assuming the assoc...
Definition Socket.cpp:74
@ eofbit
indicates that an input operation reached the end of an input sequence
Definition Socket.h:82
@ failbit
indicates that an input operation failed to read the expected characters, or that an output operation...
Definition Socket.h:84
Streambuf class.
Definition Streambuf.h:91
int sputc(char c_)
This function stores c just after the put pointer, and advances the pointer one position,...
Definition Streambuf.h:568
int sbumpc()
This function should probably have been called `‘sgetc’'.
Definition Streambuf.h:539
int in_avail()
This function returns the number of characters immediately available in the get area.
Definition Streambuf.h:399
void unbuffered(int i_)
If i_ is non-zero, then all IO operations are buffered.
Definition Streambuf.h:417
int sputn(char *b_, int len_)
From the location pointed to by ptr, stores exactly len characters after the put pointer,...
Definition Streambuf.h:579
int sgetn(char *b_, int len_)
This function gets the next len_ characters following the get pointer, copying them to the char array...
Definition Streambuf.h:559
@ SOCK
Class Socket & friends messages
Definition LogMask.h:41
@ SOCKTRACE
Extended Socket & friends messages
Definition LogMask.h:42
@ ASSAERR
ASSA and system errors
Definition LogMask.h:34
bool is_valid_handler(handler_t socket_)
Detect socket() error in a portable way.
void disable_handler(handler_t &socket_)
Set socket descriptor to invalid value in a portable way.
int get_errno()
Fetch error number in a portable way.