00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "IPSocket.h"
00019 #include "NetUtils.h"
00020 #include "debug/Log.h"
00021 #include "debug/DebugUtils.h"
00022
00023 #include <string.h>
00024 #include <unistd.h>
00025 #include <fcntl.h>
00026 #include <errno.h>
00027 #include <sys/ioctl.h>
00028 #include <sys/types.h>
00029 #include <sys/socket.h>
00030 #include <sys/uio.h>
00031 #include <sys/poll.h>
00032 #include <netinet/in.h>
00033 #include <netinet/tcp.h>
00034 #include <arpa/inet.h>
00035
00036 namespace oasys {
00037
00038 IPSocket::IPSocket(int socktype, const char* logbase)
00039 : Logger("IPSocket", logbase)
00040 {
00041 state_ = INIT;
00042 local_addr_ = INADDR_ANY;
00043 local_port_ = 0;
00044 remote_addr_ = INADDR_NONE;
00045 remote_port_ = 0;
00046 fd_ = -1;
00047 socktype_ = socktype;
00048 logfd_ = true;
00049 }
00050
00051 IPSocket::IPSocket(int socktype, int sock,
00052 in_addr_t remote_addr, u_int16_t remote_port,
00053 const char* logbase)
00054 : Logger("IPSocket", "%s/%d", logbase, sock)
00055 {
00056 fd_ = sock;
00057 socktype_ = socktype;
00058
00059 state_ = ESTABLISHED;
00060 local_addr_ = INADDR_NONE;
00061 local_port_ = 0;
00062 remote_addr_ = remote_addr;
00063 remote_port_ = remote_port;
00064
00065 configure();
00066 }
00067
00068 IPSocket::~IPSocket()
00069 {
00070 close();
00071 }
00072
00073 void
00074 IPSocket::init_socket()
00075 {
00076
00077 ASSERT(state_ == INIT || state_ == FINI);
00078 ASSERT(fd_ == -1);
00079 state_ = INIT;
00080
00081 fd_ = socket(PF_INET, socktype_, 0);
00082 if (fd_ == -1) {
00083 logf(LOG_ERR, "error creating socket: %s", strerror(errno));
00084 return;
00085 }
00086
00087 if (logfd_)
00088 Logger::logpath_appendf("/%d", fd_);
00089
00090 logf(LOG_DEBUG, "created socket %d", fd_);
00091
00092 configure();
00093 }
00094
00095 const char*
00096 IPSocket::statetoa(state_t state)
00097 {
00098 switch (state) {
00099 case INIT: return "INIT";
00100 case LISTENING: return "LISTENING";
00101 case CONNECTING: return "CONNECTING";
00102 case ESTABLISHED: return "ESTABLISHED";
00103 case RDCLOSED: return "RDCLOSED";
00104 case WRCLOSED: return "WRCLOSED";
00105 case CLOSED: return "CLOSED";
00106 case FINI: return "FINI";
00107 }
00108 ASSERT(0);
00109 return NULL;
00110 }
00111
00112 void
00113 IPSocket::set_state(state_t state)
00114 {
00115 logf(LOG_DEBUG, "state %s -> %s", statetoa(state_), statetoa(state));
00116 state_ = state;
00117 }
00118
00119 int
00120 IPSocket::bind(in_addr_t local_addr, u_int16_t local_port)
00121 {
00122 struct sockaddr_in sa;
00123
00124 if (fd_ == -1) init_socket();
00125
00126 local_addr_ = local_addr;
00127 local_port_ = local_port;
00128
00129 logf(LOG_DEBUG, "binding to %s:%d", intoa(local_addr), local_port);
00130
00131 memset(&sa, 0, sizeof(sa));
00132 sa.sin_family = AF_INET;
00133 sa.sin_addr.s_addr = local_addr_;
00134 sa.sin_port = htons(local_port_);
00135 if (::bind(fd_, (struct sockaddr*) &sa, sizeof(sa)) != 0) {
00136 int err = errno;
00137 logf(LOG_ERR, "error binding to %s:%d: %s",
00138 intoa(local_addr_), local_port_, strerror(err));
00139 return -1;
00140 }
00141
00142 return 0;
00143 }
00144
00145 int
00146 IPSocket::connect()
00147 {
00148 struct sockaddr_in sa;
00149
00150 if (ESTABLISHED == state_)
00151 return 0;
00152
00153 if (fd_ == -1) init_socket();
00154
00155 log_debug("connecting to %s:%d", intoa(remote_addr_), remote_port_);
00156
00157 memset(&sa, 0, sizeof(sa));
00158 sa.sin_family = AF_INET;
00159 sa.sin_addr.s_addr = remote_addr_;
00160 sa.sin_port = htons(remote_port_);
00161
00162 set_state(CONNECTING);
00163
00164 if (::connect(fd_, (struct sockaddr*)&sa, sizeof(sa)) < 0) {
00165 if (errno == EISCONN)
00166 log_debug("already connected to %s:%d",
00167 intoa(remote_addr_), remote_port_);
00168 else if (errno == EINPROGRESS) {
00169 log_debug("delayed connect to %s:%d (EINPROGRESS)",
00170 intoa(remote_addr_), remote_port_);
00171 } else {
00172 log_debug("error connecting to %s:%d: %s",
00173 intoa(remote_addr_), remote_port_, strerror(errno));
00174 }
00175
00176 return -1;
00177 }
00178
00179 set_state(ESTABLISHED);
00180
00181 return 0;
00182 }
00183
00184 int
00185 IPSocket::async_connect_result()
00186 {
00187 ASSERT(state_ == CONNECTING);
00188
00189 int result;
00190 socklen_t len = sizeof(result);
00191 logf(LOG_DEBUG, "getting connect result");
00192 if (::getsockopt(fd_, SOL_SOCKET, SO_ERROR, &result, &len) != 0) {
00193 logf(LOG_ERR, "error getting connect result: %s", strerror(errno));
00194 return errno;
00195 }
00196
00197 if (result == 0) {
00198 set_state(ESTABLISHED);
00199 }
00200
00201 return result;
00202 }
00203
00204 int
00205 IPSocket::connect(in_addr_t remote_addr, u_int16_t remote_port)
00206 {
00207 remote_addr_ = remote_addr;
00208 remote_port_ = remote_port;
00209
00210 return connect();
00211 }
00212
00213 void
00214 IPSocket::configure()
00215 {
00216 if (params_.reuseaddr_) {
00217 int y = 1;
00218 logf(LOG_DEBUG, "setting SO_REUSEADDR");
00219 if (::setsockopt(fd_, SOL_SOCKET, SO_REUSEADDR, &y, sizeof y) != 0) {
00220 logf(LOG_WARN, "error setting SO_REUSEADDR: %s",
00221 strerror(errno));
00222 }
00223 }
00224
00225 if (params_.reuseport_) {
00226 #ifdef SO_REUSEPORT
00227 int y = 1;
00228 logf(LOG_DEBUG, "setting SO_REUSEPORT");
00229 if (::setsockopt(fd_, SOL_SOCKET, SO_REUSEPORT, &y, sizeof y) != 0) {
00230 logf(LOG_WARN, "error setting SO_REUSEPORT: %s",
00231 strerror(errno));
00232 }
00233 #else
00234 logf(LOG_WARN, "error setting SO_REUSEPORT: not implemented");
00235 #endif
00236 }
00237
00238 if (socktype_ == SOCK_STREAM && params_.tcp_nodelay_) {
00239 int y = 1;
00240 logf(LOG_DEBUG, "setting TCP_NODELAY");
00241 if (::setsockopt(fd_, IPPROTO_IP, TCP_NODELAY, &y, sizeof y) != 0) {
00242 logf(LOG_WARN, "error setting TCP_NODELAY: %s",
00243 strerror(errno));
00244 }
00245 }
00246
00247 if (socktype_ == SOCK_DGRAM && params_.broadcast_) {
00248 int y = 1;
00249 logf(LOG_DEBUG, "setting SO_BROADCAST");
00250
00251 if (::setsockopt(fd_, SOL_SOCKET, SO_BROADCAST, &y, sizeof(y)) != 0) {
00252 logf(LOG_WARN, "error setting SO_BROADCAST: %s",
00253 strerror(errno));
00254 }
00255 }
00256
00257 if (socktype_ == SOCK_DGRAM && params_.multicast_) {
00258
00259
00260 struct ip_mreq mcast_request;
00261 memset(&mcast_request,0,sizeof(struct ip_mreq));
00262
00263
00264
00265 in_addr_t mcast_addr = inet_addr("224.0.0.0");
00266 if (mcast_addr & remote_addr_ != mcast_addr) {
00267 logf(LOG_WARN, "multicast option set on non-multicast address: "
00268 "%s",intoa(remote_addr_));
00269 return;
00270 }
00271
00272
00273 mcast_request.imr_multiaddr.s_addr = remote_addr_;
00274 mcast_request.imr_interface.s_addr = INADDR_ANY;
00275
00276
00277 if (::setsockopt(fd_, IPPROTO_IP, IP_ADD_MEMBERSHIP,
00278 (void*) &mcast_request, sizeof (struct ip_mreq)) < 0)
00279 {
00280 logf(LOG_WARN, "error setting multicast options: %s",
00281 strerror(errno));
00282 }
00283
00284
00285 u_char ttl = (u_char) params_.mcast_ttl_ & 0xff;
00286 if (::setsockopt(fd_, IPPROTO_IP, IP_MULTICAST_TTL, (void*) &ttl, 1)
00287 < 0) {
00288 logf(LOG_WARN, "error setting multicast ttl: %s",
00289 strerror(errno));
00290 }
00291 }
00292
00293 if (params_.recv_bufsize_ > 0) {
00294 logf(LOG_DEBUG, "setting SO_RCVBUF to %d",
00295 params_.recv_bufsize_);
00296
00297 if (::setsockopt(fd_, SOL_SOCKET, SO_RCVBUF,
00298 ¶ms_.recv_bufsize_,
00299 sizeof (params_.recv_bufsize_)) < 0)
00300 {
00301 logf(LOG_WARN, "error setting SO_RCVBUF to %d: %s",
00302 params_.recv_bufsize_, strerror(errno));
00303 }
00304 }
00305
00306 if (params_.send_bufsize_ > 0) {
00307 logf(LOG_WARN, "setting SO_SNDBUF to %d",
00308 params_.send_bufsize_);
00309
00310 if (::setsockopt(fd_, SOL_SOCKET, SO_SNDBUF,
00311 ¶ms_.send_bufsize_,
00312 sizeof params_.send_bufsize_) < 0)
00313 {
00314 logf(LOG_WARN, "error setting SO_SNDBUF to %d: %s",
00315 params_.send_bufsize_, strerror(errno));
00316 }
00317 }
00318 }
00319
00320 int
00321 IPSocket::close()
00322 {
00323 logf(LOG_DEBUG, "closing socket in state %s", statetoa(state_));
00324
00325 if (fd_ == -1) {
00326 ASSERT(state_ == INIT || state_ == FINI);
00327 return 0;
00328 }
00329
00330 if (::close(fd_) != 0) {
00331 logf(LOG_ERR, "error closing socket in state %s: %s",
00332 statetoa(state_), strerror(errno));
00333 return -1;
00334 }
00335
00336 set_state(FINI);
00337 fd_ = -1;
00338 return 0;
00339 }
00340
00341 int
00342 IPSocket::shutdown(int how)
00343 {
00344 const char* howstr;
00345
00346 switch (how) {
00347 case SHUT_RD: howstr = "R"; break;
00348 case SHUT_WR: howstr = "W"; break;
00349 case SHUT_RDWR: howstr = "RW"; break;
00350
00351 default:
00352 logf(LOG_ERR, "shutdown invalid mode %d", how);
00353 return -1;
00354 }
00355
00356 logf(LOG_DEBUG, "shutdown(%s) state %s", howstr, statetoa(state_));
00357
00358 if (state_ == INIT || state_ == FINI) {
00359 ASSERT(fd_ == -1);
00360 return 0;
00361 }
00362
00363 if (::shutdown(fd_, how) != 0) {
00364 logf(LOG_ERR, "error in shutdown(%s) state %s: %s",
00365 howstr, statetoa(state_), strerror(errno));
00366 }
00367
00368 if (state_ == ESTABLISHED) {
00369 if (how == SHUT_RD) { set_state(RDCLOSED); }
00370 if (how == SHUT_WR) { set_state(WRCLOSED); }
00371 if (how == SHUT_RDWR) { set_state(CLOSED); }
00372
00373 } else if (state_ == RDCLOSED && how == SHUT_WR) {
00374 set_state(CLOSED);
00375
00376 } else if (state_ == WRCLOSED && how == SHUT_RD) {
00377 set_state(CLOSED);
00378
00379 } else {
00380 logf(LOG_ERR, "invalid state %s for shutdown(%s)",
00381 statetoa(state_), howstr);
00382 return -1;
00383 }
00384
00385 return 0;
00386 }
00387
00388 int
00389 IPSocket::send(const char* bp, size_t len, int flags)
00390 {
00391 return IO::send(fd_, bp, len, flags, get_notifier(), logpath_);
00392 }
00393
00394 int
00395 IPSocket::sendto(char* bp, size_t len, int flags,
00396 in_addr_t addr, u_int16_t port)
00397 {
00398 struct sockaddr_in sa;
00399 memset(&sa, 0, sizeof(sa));
00400 sa.sin_family = AF_INET;
00401 sa.sin_addr.s_addr = addr;
00402 sa.sin_port = htons(port);
00403
00404 return IO::sendto(fd_, bp, len, flags, (sockaddr*)&sa,
00405 sizeof(sa), get_notifier(), logpath_);
00406 }
00407
00408 int
00409 IPSocket::sendmsg(const struct msghdr* msg, int flags)
00410 {
00411 return IO::sendmsg(fd_, msg, flags, get_notifier(), logpath_);
00412 }
00413
00414 int
00415 IPSocket::recv(char* bp, size_t len, int flags)
00416 {
00417 return IO::recv(fd_, bp, len, flags,
00418 get_notifier(), logpath_);
00419 }
00420
00421 int
00422 IPSocket::recvfrom(char* bp, size_t len, int flags,
00423 in_addr_t *addr, u_int16_t *port)
00424 {
00425 struct sockaddr_in sa;
00426 socklen_t sl = sizeof(sa);
00427 memset(&sa, 0, sizeof(sa));
00428
00429 int cc = IO::recvfrom(fd_, bp, len, flags, (sockaddr*)&sa, &sl,
00430 get_notifier(), logpath_);
00431
00432 if (cc < 0) {
00433 if (cc != IOINTR)
00434 logf(LOG_ERR, "error in recvfrom(): %s", strerror(errno));
00435 return cc;
00436 }
00437
00438 if (addr)
00439 *addr = sa.sin_addr.s_addr;
00440
00441 if (port)
00442 *port = htons(sa.sin_port);
00443
00444 return cc;
00445 }
00446
00447 int
00448 IPSocket::recvmsg(struct msghdr* msg, int flags)
00449 {
00450 return IO::recvmsg(fd_, msg, flags, get_notifier(), logpath_);
00451 }
00452
00453 int
00454 IPSocket::poll_sockfd(int events, int* revents, int timeout_ms)
00455 {
00456 short s_events = events;
00457 short s_revents;
00458
00459 int cc = IO::poll_single(fd_, s_events, &s_revents, timeout_ms,
00460 get_notifier(), logpath_);
00461
00462 if (revents != 0) {
00463 *revents = s_revents;
00464 }
00465
00466 return cc;
00467 }
00468
00469 }