00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <sys/errno.h>
00013
00014 #include "assa/MemDump.h"
00015 #include "assa/IPv4Socket.h"
00016
00017 using namespace ASSA;
00018
00019 Streambuf*
00020 IPv4Socket::
00021 rdbuf (Streambuf* sb_)
00022 {
00023 trace_with_mask("IPv4Socket::rdbuf(sb_)",SOCKTRACE);
00024
00025 if (sb_ == 0 || sb_ == m_rdbuf) {
00026 return (sb_);
00027 }
00028 Streambuf* old = m_rdbuf;
00029 m_rdbuf = sb_;
00030 return (old);
00031 }
00032
00033
00034 bool
00035 IPv4Socket::
00036 open (const int domain_)
00037 {
00038 trace_with_mask("IPv4Socket::open",SOCKTRACE);
00039
00040 m_type = domain_;
00041 m_fd = ::socket(domain_, SOCK_STREAM, 0);
00042 if (m_fd < 0) {
00043 EL((ERROR,"OS::socket() error\n"));
00044 setstate (Socket::failbit);
00045 return (false);
00046 }
00047 clear ();
00048 turnOptionOn (Socket::nonblocking);
00049 return (true);
00050 }
00051
00052 bool
00053 IPv4Socket::
00054 close()
00055 {
00056 trace_with_mask("IPv4Socket::close()",SOCKTRACE);
00057
00058 if (m_fd >= 0) {
00059 DL((SOCK,"Closed FD: %d\n",m_fd));
00060
00061
00062 flush ();
00063 ::close(m_fd);
00064 setstate (Socket::failbit);
00065 m_fd = -1;
00066
00067
00068
00069
00070
00071
00072
00073 if (m_rdbuf && m_rdbuf->in_avail ()) {
00074 for (char c; (c=m_rdbuf->sbumpc ()) != EOF;) { }
00075 }
00076 }
00077 return (true);
00078 }
00079
00080 bool
00081 IPv4Socket::
00082 connect (const Address& his_address_)
00083 {
00084 trace_with_mask("IPv4Socket::connect()",SOCKTRACE);
00085
00086 if (m_fd < 0 && open (getDomain()) == false) {
00087 return false;
00088 }
00089
00090 int ret = ::connect (m_fd,
00091 (SA*) his_address_.getAddress(),
00092 his_address_.getLength());
00093 if (ret < 0) {
00094 if (errno == EINPROGRESS) {
00095 DL((SOCK,"FD: %d OS::connect() error\n",m_fd));
00096 }
00097 else {
00098 EL((SOCK,"FD: %d OS::connect() error\n",m_fd));
00099 }
00100 return (false);
00101 }
00102 clear ();
00103 DL((SOCK,"Connection opened on FD: %d\n", m_fd));
00104 return (true);
00105 }
00106
00107 bool
00108 IPv4Socket::
00109 bind (const Address& addr_)
00110 {
00111 trace_with_mask("IPv4Socket::bind",SOCKTRACE);
00112
00113
00114 if ( getDomain() == AF_UNIX ) {
00115 char* p = ((SA_UN *) addr_.getAddress())->sun_path;
00116 m_path = new char[strlen(p)+1];
00117 strcpy(m_path, p);
00118 struct stat sb;
00119
00120 if (stat (m_path, &sb) == 0) {
00121 if ( S_ISSOCK(sb.st_mode) || S_ISFIFO(sb.st_mode) ) {
00122 unlink(m_path);
00123 }
00124 }
00125 }
00126
00127
00128
00129
00130
00131 Assure_return ( turnOptionOn (reuseaddr) );
00132
00133 int rt = ::bind(m_fd, addr_.getAddress(), addr_.getLength());
00134
00135 if ( rt < 0) {
00136 EL((SOCK,"::bind() FD: %d failed\n",m_fd));
00137 setstate (Socket::failbit);
00138 return (false);
00139 }
00140 Assure_return ( (::listen(m_fd, 5) == 0) );
00141 return (true);
00142 }
00143
00144 IPv4Socket*
00145 IPv4Socket::
00146 accept ()
00147 {
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159 trace_with_mask("IPv4Socket::accept",SOCKTRACE);
00160
00161 socklen_t length = 0;
00162 int new_fd = -1;
00163 SA* remote_address = NULL;
00164
00165 if ( getDomain() == AF_UNIX ) {
00166 length = sizeof(struct sockaddr_in);
00167 remote_address = (SA*) new SA_IN;
00168 }
00169 else {
00170 remote_address = (SA*) new SA_UN;
00171 length = sizeof(struct sockaddr_un);
00172 }
00173 memset(remote_address, 0, length);
00174
00175 #ifndef __CYGWIN32__
00176 new_fd = ::accept(m_fd, remote_address, &length);
00177 #else
00178 new_fd = ::accept(m_fd, remote_address, (int*)&length);
00179 #endif
00180
00181 if ( new_fd < 0 ) {
00182 EL((ERROR,"OS::accept() failed\n"));
00183 close();
00184 return NULL;
00185 }
00186 if (length == sizeof(SA_IN)) {
00187 SA_IN* sa_in = (SA_IN*) remote_address;
00188
00189 DL((SOCK,"Accepted new TCP connection from Addr %s, port %d\n",
00190 inet_ntoa(sa_in->sin_addr), ntohs( sa_in->sin_port)));
00191 }
00192 else {
00193 SA_UN* sa_un = (SA_UN*) remote_address;
00194 DL((SOCK,"Accepted new UNIX connection from %s\n",
00195 sa_un->sun_path));
00196 }
00197 delete remote_address;
00198
00199 IPv4Socket* s = new IPv4Socket (new_fd);
00200 s->clear ();
00201 s->turnOptionOn (Socket::nonblocking);
00202 return s;
00203 }
00204
00205 int
00206 IPv4Socket::
00207 read (char* packet_, const unsigned int size_)
00208 {
00209 trace_with_mask("IPv4Socket::read",SOCKTRACE);
00210
00211 register int len;
00212 register int sz = size_;
00213 char* tmp = packet_;
00214
00215 if (m_fd < 0) return -1;
00216
00217 len = 0;
00218 if (m_rdbuf->unbuffered ()) {
00219
00220
00221
00222
00223
00224
00225
00226
00227 if ((len = m_rdbuf->sbumpc ()) >= 0) {
00228 *tmp = len;
00229 len = 1;
00230 }
00231 }
00232 else {
00233 len = m_rdbuf->sgetn (tmp, sz);
00234 }
00235 if (len == -1) {
00236
00237
00238
00239 if (errno != EWOULDBLOCK) {
00240 EL((ERROR,"::read(fd = %d) \n",m_fd));
00241 setstate (Socket::failbit);
00242 }
00243 return len;
00244 }
00245 tmp += len;
00246 sz -= len;
00247
00248 if ((size_ - sz) == 0)
00249 {
00250 DL((SOCK,"Peer has dropped connection FD: %d\n",m_fd));
00251 setstate (Socket::failbit | Socket::eofbit);
00252 return 0;
00253 }
00254
00255 DL((SOCKTRACE,"==> FD: %d Received %d bytes\n", m_fd, size_ - sz));
00256 MemDump::dump_to_log (SOCKTRACE, "Data received:", packet_, size_ - sz);
00257
00258
00259
00260
00261
00262
00263 return (size_ - sz);
00264 }
00265
00266 int
00267 IPv4Socket::
00268 write(const char* packet_, const unsigned int size_)
00269 {
00270 trace_with_mask("IPv4Socket::write()",SOCKTRACE);
00271
00272 register int ret = 0;
00273
00274 if (m_fd < 0) return -1;
00275
00276 if (m_rdbuf->unbuffered ()) {
00277 register int wlen = size_;
00278 register char* p = (char*) packet_;
00279
00280 while (wlen-- > 0) {
00281 if (m_rdbuf->sputc (*p++) == EOF) {
00282 return (EOF);
00283 }
00284 }
00285 ret = p - packet_;
00286 }
00287 else
00288 ret = m_rdbuf->sputn ((char*) packet_, size_);
00289
00290 if (ret > 0) {
00291 DL((SOCK,"<= FD: %d Wrote %d bytes (requested %d bytes)\n",
00292 m_fd, ret, size_));
00293 MemDump::dump_to_log (SOCK, "Data written", (char*)packet_, ret);
00294 }
00295 return ret;
00296 }
00297
00298 IPv4Socket*
00299 IPv4Socket::
00300 clone () const
00301 {
00302 const char self[] = "IPv4Socket::clone";
00303 trace_with_mask(self,SOCKTRACE);
00304
00305 int nfd = dup (m_fd);
00306
00307 IPv4Socket* s = new IPv4Socket (nfd);
00308
00309 DL((SOCK,"Original socket has %d bytes in its get_area\n",
00310 m_rdbuf->in_avail ()));
00311
00312 if (nfd < 0 || !good ()) {
00313 s->setstate (Socket::failbit);
00314 }
00315 else {
00316 s->clear ();
00317 }
00318 return s;
00319 }
00320
00321