|
|
873e9f |
|
|
|
937c1c |
#include <cstring></cstring>
|
|
|
f6f04f |
#include <cstdlib></cstdlib>
|
|
|
460064 |
#include <cstdio></cstdio>
|
|
|
460064 |
#include <cerrno></cerrno>
|
|
|
937c1c |
|
|
|
937c1c |
#include <fcntl.h></fcntl.h>
|
|
|
937c1c |
#include <unistd.h></unistd.h>
|
|
|
f6f04f |
#include <poll.h></poll.h>
|
|
|
937c1c |
#include <sys types.h=""></sys>
|
|
|
937c1c |
#include <sys socket.h=""></sys>
|
|
|
937c1c |
#include <netinet in.h=""></netinet>
|
|
|
937c1c |
#include <netinet tcp.h=""></netinet>
|
|
|
937c1c |
#include <netdb.h></netdb.h>
|
|
|
937c1c |
|
|
|
937c1c |
|
|
|
873e9f |
#include "socket.h"
|
|
|
937c1c |
|
|
|
937c1c |
|
|
|
937c1c |
|
|
|
460064 |
static void addressToInaddr(const Address &address, struct sockaddr_in &addr) {
|
|
|
937c1c |
memset(&addr, 0, sizeof(addr));
|
|
|
937c1c |
addr.sin_family = AF_INET;
|
|
|
937c1c |
addr.sin_addr.s_addr = address.ipUInt;
|
|
|
937c1c |
addr.sin_port = htons(address.port);
|
|
|
937c1c |
}
|
|
|
937c1c |
|
|
|
937c1c |
static bool configureTcpSocket(int sockId) {
|
|
|
937c1c |
int tcp_nodelay = 1;
|
|
|
937c1c |
return 0 == setsockopt(sockId, IPPROTO_TCP, TCP_NODELAY, &tcp_nodelay, sizeof(int))
|
|
|
937c1c |
&& 0 == fcntl(sockId, F_SETFL, fcntl(sockId, F_GETFL, 0) | O_NONBLOCK);
|
|
|
937c1c |
}
|
|
|
937c1c |
|
|
|
937c1c |
|
|
|
937c1c |
|
|
|
f6f04f |
Poll::Poll() { }
|
|
|
f6f04f |
Poll::~Poll() { }
|
|
|
f6f04f |
|
|
|
f6f04f |
bool Poll::wait(Time duration) {
|
|
|
f6f04f |
const size_t count = list.size();
|
|
|
f6f04f |
const size_t size = sizeof(struct pollfd) * count;
|
|
|
f6f04f |
if (data.size() < size)
|
|
|
f6f04f |
data.resize(size);
|
|
|
f6f04f |
|
|
|
f6f04f |
int mills = (int)((duration + rand()%1000)/1000);
|
|
|
f6f04f |
int res;
|
|
|
f6f04f |
|
|
|
f6f04f |
if (size) {
|
|
|
f6f04f |
memset(data.data(), 0, size);
|
|
|
f6f04f |
struct pollfd *pfdFirst = (struct pollfd *)data.data();
|
|
|
f6f04f |
struct pollfd *pfd = pfdFirst;
|
|
|
f6f04f |
for(List::const_iterator i = list.begin(); i != list.end(); ++i, ++pfd) {
|
|
|
f6f04f |
pfd->fd = i->sockId;
|
|
|
f6f04f |
pfd->events = POLLRDHUP;
|
|
|
f6f04f |
if (i->wantRead) pfd->events |= POLLIN;
|
|
|
f6f04f |
if (i->wantWrite) pfd->events |= POLLOUT;
|
|
|
f6f04f |
}
|
|
|
f6f04f |
|
|
|
f6f04f |
res = poll(pfdFirst, count, mills);
|
|
|
f6f04f |
|
|
|
f6f04f |
if (res > 0) {
|
|
|
f6f04f |
struct pollfd *pfd = pfdFirst;
|
|
|
f6f04f |
for(List::iterator i = list.begin(); i != list.end(); ++i, ++pfd) {
|
|
|
460064 |
unsigned int e = pfd->revents;
|
|
|
f6f04f |
i->canRead = (bool)(e & POLLIN);
|
|
|
f6f04f |
i->canWrite = (bool)(e & POLLOUT);
|
|
|
f6f04f |
i->closed = (bool)(e & (POLLHUP | POLLRDHUP | POLLERR | POLLNVAL));
|
|
|
f6f04f |
}
|
|
|
f6f04f |
}
|
|
|
f6f04f |
} else {
|
|
|
f6f04f |
res = poll(NULL, 0, mills);
|
|
|
f6f04f |
}
|
|
|
f6f04f |
|
|
|
f6f04f |
return res >= 0;
|
|
|
f6f04f |
}
|
|
|
f6f04f |
|
|
|
f6f04f |
|
|
|
f6f04f |
|
|
|
937c1c |
int Socket::tcpConnect(const Address &address) {
|
|
|
937c1c |
int sockId = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
|
|
937c1c |
if (sockId < 0) return -1;
|
|
|
937c1c |
struct sockaddr_in addr;
|
|
|
937c1c |
addressToInaddr(address, addr);
|
|
|
937c1c |
if ( 0 != ::connect(sockId, (struct sockaddr*)&addr, sizeof(addr))
|
|
|
937c1c |
|| !configureTcpSocket(sockId) )
|
|
|
937c1c |
{ ::close(sockId); return -1; }
|
|
|
937c1c |
return sockId;
|
|
|
937c1c |
}
|
|
|
937c1c |
|
|
|
937c1c |
|
|
|
937c1c |
int Socket::tcpListen(const Address &address) {
|
|
|
937c1c |
int sockId = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
|
|
937c1c |
if (sockId < 0) return -1;
|
|
|
937c1c |
struct sockaddr_in addr;
|
|
|
937c1c |
addressToInaddr(address, addr);
|
|
|
937c1c |
if ( 0 != ::bind(sockId, (struct sockaddr*)&addr, sizeof(addr))
|
|
|
937c1c |
|| 0 != ::listen(sockId, 16)
|
|
|
937c1c |
|| !configureTcpSocket(sockId) )
|
|
|
937c1c |
{ ::close(sockId); return -1; }
|
|
|
937c1c |
return sockId;
|
|
|
937c1c |
}
|
|
|
937c1c |
|
|
|
937c1c |
|
|
|
460064 |
int Socket::tcpAccept(int sockId, Address &address) {
|
|
|
460064 |
address = Address();
|
|
|
937c1c |
struct sockaddr_in addr = {};
|
|
|
937c1c |
addr.sin_family = AF_INET;
|
|
|
937c1c |
socklen_t len = sizeof(addr);
|
|
|
937c1c |
int newSockId = ::accept(sockId, (struct sockaddr*)&addr, &len);
|
|
|
937c1c |
if (newSockId < 0) return -1;
|
|
|
937c1c |
if (!configureTcpSocket(newSockId))
|
|
|
937c1c |
{ ::close(newSockId); return -1; }
|
|
|
460064 |
address.ipUInt = addr.sin_addr.s_addr;
|
|
|
460064 |
address.port = ntohs(addr.sin_port);
|
|
|
937c1c |
return newSockId;
|
|
|
937c1c |
}
|
|
|
937c1c |
|
|
|
937c1c |
|
|
|
937c1c |
int Socket::tcpSendAsync(int sockId, const void *data, int size) {
|
|
|
937c1c |
int res = ::send(sockId, data, size, MSG_DONTWAIT);
|
|
|
937c1c |
return res > 0 ? res : 0;
|
|
|
937c1c |
}
|
|
|
937c1c |
|
|
|
937c1c |
|
|
|
937c1c |
int Socket::tcpRecvAsync(int sockId, void *data, int size) {
|
|
|
937c1c |
int res = ::recv(sockId, data, size, MSG_DONTWAIT);
|
|
|
937c1c |
return res > 0 ? res : 0;
|
|
|
937c1c |
}
|
|
|
937c1c |
|
|
|
937c1c |
|
|
|
937c1c |
int Socket::udpBind(const Address &address) {
|
|
|
937c1c |
int sockId = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
|
|
937c1c |
if (sockId < 0) return -1;
|
|
|
937c1c |
|
|
|
937c1c |
struct sockaddr_in addr;
|
|
|
937c1c |
addressToInaddr(address, addr);
|
|
|
937c1c |
if (0 != ::bind(sockId, (struct sockaddr*)&addr, sizeof(addr))) {
|
|
|
937c1c |
::close(sockId);
|
|
|
937c1c |
return -1;
|
|
|
937c1c |
}
|
|
|
937c1c |
|
|
|
937c1c |
return sockId;
|
|
|
937c1c |
}
|
|
|
937c1c |
|
|
|
937c1c |
|
|
|
937c1c |
int Socket::udpSend(int sockId, const Address &address, const void *data, int size) {
|
|
|
937c1c |
struct sockaddr_in addr;
|
|
|
937c1c |
addressToInaddr(address, addr);
|
|
|
937c1c |
int res = ::sendto(sockId, data, size, 0, (struct sockaddr*)&addr, sizeof(addr));
|
|
|
937c1c |
return res > 0 ? res : 0;
|
|
|
937c1c |
}
|
|
|
937c1c |
|
|
|
937c1c |
|
|
|
937c1c |
int Socket::udpRecvAsync(int sockId, Address &address, void *data, int size) {
|
|
|
937c1c |
address = Address();
|
|
|
937c1c |
struct sockaddr_in addr = {};
|
|
|
937c1c |
addr.sin_family = AF_INET;
|
|
|
937c1c |
socklen_t len = sizeof(addr);
|
|
|
937c1c |
int res = ::recvfrom(sockId, data, size, MSG_DONTWAIT, (struct sockaddr*)&addr, &len);
|
|
|
937c1c |
if (res <= 0) return 0;
|
|
|
937c1c |
address.ipUInt = addr.sin_addr.s_addr;
|
|
|
937c1c |
address.port = ntohs(addr.sin_port);
|
|
|
937c1c |
return res;
|
|
|
937c1c |
}
|
|
|
937c1c |
|
|
|
937c1c |
|
|
|
937c1c |
void Socket::close(int sockId)
|
|
|
937c1c |
{ ::close(sockId); }
|
|
|
937c1c |
|