/* * @(#)Socket.cpp * * This file is part of webCDwriter - Network CD Writing. * * Copyright (C) 2002-2004 Jörg P. M. Haeger * * webCDwriter is free software. See CDWserver.cpp for details. * * Jörg Haeger, 19.04.2002 */ #include #include #include #include #include #include #include #include "BufferedReader.h" #include "InputStream.h" #include "Support.h" #include "Socket.h" Socket::Socket() { fd = -1; inputStream = NULL; inputStream2 = NULL; } Socket::Socket(int fd): inetAddress("unknown") { this->fd = fd; inputStream = new BufferedReader(fd); inputStream2 = new InputStream(fd); } Socket::Socket(const char *host, int port) { struct hostent *hostinfo = gethostbyname(host); if (hostinfo == NULL) throw new Exception("Socket: hostinfo == NULL"); fd = ::socket(PF_INET, SOCK_STREAM, 0); if (fd < 0) throw new Exception("Socket: fd < 0"); struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr = *(struct in_addr *)hostinfo->h_addr; int res = ::connect(fd, (struct sockaddr *)&addr, sizeof addr); if (res != 0) throw new Exception("Socket: cannot connect"); inputStream = new BufferedReader(fd); inputStream2 = new InputStream(fd); } Socket::~Socket() { if (inputStream2 != NULL) delete inputStream2; if (inputStream != NULL) delete inputStream; if (fd < 0) return; shutdown(fd, 1); while (1) { fd_set fdSet; FD_ZERO(&fdSet); FD_SET(fd, &fdSet); struct timeval timeout; timeout.tv_sec = 10; timeout.tv_usec = 0; int res; while (1) { res = select(FD_SETSIZE, &fdSet, NULL, NULL, &timeout); if (res != -1 || errno != EINTR) break; } if (res == 0) break; char buf[4 * 1024]; if (read(fd, buf, sizeof buf) <= 0) break; } close(fd); } String &Socket::getInetAddress() { struct sockaddr_in name; socklen_t len = sizeof name; if (getpeername(fd, (struct sockaddr *)&name, &len) == 0) { char str[256]; if (inet_ntop(name.sin_family, &name.sin_addr, str, sizeof str) != NULL) { inetAddress = new String(str); return inetAddress; } } return inetAddress; } BufferedReader &Socket::getInputStream() { return *inputStream; } InputStream &Socket::getInputStream2() { return *inputStream2; } int Socket::getOutputStream() { return fd; } int Socket::getPort() { struct sockaddr_in name; socklen_t len = sizeof name; if (getpeername(fd, (struct sockaddr *)&name, &len) == 0) return name.sin_port; return 0; } void Socket::setKeepAlive(boolean on) { int onoff = on; if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&onoff, sizeof onoff) < 0) throw new Exception(S.e + "setsockopt SO_KEEPALIVE: " + strerror(errno)); } void Socket::setSoLinger(boolean on, int linger) { struct linger li; li.l_onoff = on; li.l_linger = linger; if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (void *)&li, sizeof li) < 0) throw new Exception(S.e + "setsockopt SO_LINGER: " + strerror(errno)); } int Socket::write(const char *buf, int len) { int p = 0; while (true) { int n = ::write(fd, &buf[p], len - p); if (n < 0) { if (errno == EINTR) continue; break; } p += n; if (p >= len) break; } return p; }