|
|
71057f |
|
|
|
71057f |
#include <cstring></cstring>
|
|
|
71057f |
|
|
|
71057f |
#include <chrono></chrono>
|
|
|
71057f |
#include <thread></thread>
|
|
|
71057f |
#include <mutex></mutex>
|
|
|
71057f |
|
|
|
b42f0a |
#include <unistd.h></unistd.h>
|
|
|
b42f0a |
#include <sys types.h=""></sys>
|
|
|
b42f0a |
#include <sys socket.h=""></sys>
|
|
|
b42f0a |
#include <sys epoll.h=""></sys>
|
|
|
b42f0a |
#include <netinet in.h=""></netinet>
|
|
|
b42f0a |
|
|
|
71057f |
#include "protocol.h"
|
|
|
71057f |
#include "server.h"
|
|
|
71057f |
|
|
|
71057f |
|
|
|
61c265 |
#define DebugMSG ShowDebugMSG
|
|
|
61c265 |
|
|
|
61c265 |
|
|
|
71057f |
Server::Server():
|
|
|
b42f0a |
connFirst(), connLast()
|
|
|
71057f |
{ }
|
|
|
71057f |
|
|
|
71057f |
|
|
|
b42f0a |
Server::~Server()
|
|
|
b42f0a |
{ destroy();}
|
|
|
71057f |
|
|
|
71057f |
|
|
|
b42f0a |
bool Server::open(Protocol &protocol, void *address, size_t addressSize)
|
|
|
b42f0a |
{ OpenLock lock(*this, protocol, address, addressSize); return lock.success; }
|
|
|
71057f |
|
|
|
71057f |
|
|
|
b42f0a |
void Server::handleDisconnect(Connection &connection, bool error) {
|
|
|
b42f0a |
onDisconnect(&connection, error);
|
|
|
b42f0a |
if (!connFirst && stateLocal == STATE_CLOSING_CONNECTIONS) {
|
|
|
b42f0a |
DebugMSG("to closing");
|
|
|
b42f0a |
state = stateLocal = STATE_CLOSING;
|
|
|
b42f0a |
stateProtector.wait();
|
|
|
b42f0a |
onClose(error);
|
|
|
b42f0a |
enqueue();
|
|
|
b42f0a |
}
|
|
|
71057f |
}
|
|
|
71057f |
|
|
|
71057f |
|
|
|
b42f0a |
void Server::handleState() {
|
|
|
b42f0a |
if (stateLocal == STATE_NONE) {
|
|
|
b42f0a |
DebugMSG("none");
|
|
|
b42f0a |
int sockId = -1;
|
|
|
b42f0a |
if (addressSize >= sizeof(sa_family_t)) {
|
|
|
b42f0a |
struct sockaddr *addr = (struct sockaddr*)address;
|
|
|
b42f0a |
sockId = ::socket(addr->sa_family, SOCK_STREAM, 0);
|
|
|
b42f0a |
if (sockId >= 0) {
|
|
|
b42f0a |
initSocket(sockId);
|
|
|
b42f0a |
if ( 0 != ::bind(sockId, addr, (int)addressSize)
|
|
|
b42f0a |
|| 0 != ::listen(sockId, 128) )
|
|
|
b42f0a |
{
|
|
|
b42f0a |
DebugMSG("cannot bind/listen");
|
|
|
b42f0a |
::close(sockId);
|
|
|
b42f0a |
sockId = -1;
|
|
|
b42f0a |
}
|
|
|
b42f0a |
} else {
|
|
|
b42f0a |
DebugMSG("cannot create socket");
|
|
|
b42f0a |
}
|
|
|
b42f0a |
}
|
|
|
b42f0a |
|
|
|
b42f0a |
if (sockId >= 0) {
|
|
|
b42f0a |
DebugMSG("to open");
|
|
|
b42f0a |
prev = protocol->sockLast;
|
|
|
b42f0a |
(prev ? prev->next : protocol->sockFirst) = this;
|
|
|
b42f0a |
this->sockId = sockId;
|
|
|
b42f0a |
|
|
|
b42f0a |
updateEvents(true, false);
|
|
|
b42f0a |
|
|
|
b42f0a |
state = stateLocal = STATE_OPEN;
|
|
|
b42f0a |
stateProtector.wait();
|
|
|
b42f0a |
onOpen(address, addressSize);
|
|
|
b42f0a |
} else {
|
|
|
b42f0a |
DebugMSG("opening error -> to closed");
|
|
|
b42f0a |
onOpeningError();
|
|
|
b42f0a |
state = STATE_CLOSED;
|
|
|
b42f0a |
while(closeWaiters > 0)
|
|
|
b42f0a |
{ closeCondition.notify_all(); std::this_thread::yield(); }
|
|
|
b42f0a |
state = STATE_FINISHED;
|
|
|
b42f0a |
DebugMSG("opening error -> finished");
|
|
|
b42f0a |
}
|
|
|
71057f |
} else {
|
|
|
b42f0a |
State sw = stateWanted;
|
|
|
b42f0a |
if ( stateLocal == STATE_OPEN
|
|
|
b42f0a |
&& sw == STATE_CLOSE_REQ )
|
|
|
b42f0a |
{
|
|
|
b42f0a |
DebugMSG("to close req");
|
|
|
b42f0a |
for(Connection *conn = connFirst; conn; conn = conn->srvNext)
|
|
|
b42f0a |
conn->closeReq();
|
|
|
b42f0a |
updateEvents(false, false);
|
|
|
b42f0a |
state = stateLocal = STATE_CLOSE_REQ;
|
|
|
b42f0a |
stateProtector.wait();
|
|
|
b42f0a |
onCloseReqested();
|
|
|
b42f0a |
}
|
|
|
71057f |
|
|
|
b42f0a |
if ( stateLocal >= STATE_OPEN
|
|
|
b42f0a |
&& stateLocal <= STATE_CLOSE_REQ
|
|
|
b42f0a |
&& sw == STATE_CLOSING )
|
|
|
71057f |
{
|
|
|
b42f0a |
DebugMSG("to closing connections");
|
|
|
b42f0a |
updateEvents(false, false);
|
|
|
b42f0a |
if (connFirst) {
|
|
|
b42f0a |
for(Connection *conn = connFirst; conn; conn = conn->srvNext)
|
|
|
b42f0a |
conn->close(true);
|
|
|
b42f0a |
state = stateLocal = STATE_CLOSING_CONNECTIONS;
|
|
|
b42f0a |
stateProtector.wait();
|
|
|
b42f0a |
} else {
|
|
|
b42f0a |
DebugMSG("to closing");
|
|
|
b42f0a |
state = stateLocal = STATE_CLOSING;
|
|
|
b42f0a |
stateProtector.wait();
|
|
|
b42f0a |
onClose(error);
|
|
|
71057f |
}
|
|
|
71057f |
}
|
|
|
71057f |
|
|
|
b42f0a |
if ( stateLocal == STATE_CLOSING && !enqueued ) {
|
|
|
b42f0a |
DebugMSG("to closed");
|
|
|
b42f0a |
if (sockId >= 0) {
|
|
|
b42f0a |
struct epoll_event event = {};
|
|
|
b42f0a |
epoll_ctl(protocol->epollFd, EPOLL_CTL_DEL, sockId, &event);
|
|
|
b42f0a |
::close(sockId);
|
|
|
b42f0a |
sockId = -1;
|
|
|
b42f0a |
}
|
|
|
b42f0a |
events = 0xffffffff;
|
|
|
b42f0a |
(prev ? prev->next : protocol->sockFirst) = next;
|
|
|
b42f0a |
(next ? next->prev : protocol->sockLast ) = prev;
|
|
|
b42f0a |
protocol = nullptr;
|
|
|
b42f0a |
memset(this->address, 0, sizeof(address));
|
|
|
b42f0a |
addressSize = 0;
|
|
|
b42f0a |
stateWanted = STATE_NONE;
|
|
|
b42f0a |
stateLocal = STATE_NONE;
|
|
|
b42f0a |
DebugMSG("closeWaiters");
|
|
|
b42f0a |
state = STATE_CLOSED;
|
|
|
b42f0a |
while(closeWaiters > 0)
|
|
|
b42f0a |
{ closeCondition.notify_all(); std::this_thread::yield(); }
|
|
|
b42f0a |
state = STATE_FINISHED;
|
|
|
b42f0a |
DebugMSG("finished");
|
|
|
b42f0a |
}
|
|
|
b42f0a |
}
|
|
|
b42f0a |
}
|
|
|
b42f0a |
|
|
|
b42f0a |
|
|
|
b42f0a |
void Server::handleEvents(unsigned int events) {
|
|
|
b42f0a |
if (events & (EPOLLHUP | EPOLLERR)) {
|
|
|
b42f0a |
if ( stateLocal >= STATE_OPEN
|
|
|
b42f0a |
&& stateLocal < STATE_CLOSING )
|
|
|
b42f0a |
close((bool)(events & EPOLLERR));
|
|
|
b42f0a |
return;
|
|
|
71057f |
}
|
|
|
71057f |
|
|
|
b42f0a |
if (events & EPOLLIN) {
|
|
|
b42f0a |
if ( stateLocal >= STATE_OPEN
|
|
|
b42f0a |
&& stateLocal < STATE_CLOSE_REQ)
|
|
|
b42f0a |
{
|
|
|
b42f0a |
unsigned char address[MAX_ADDR_SIZE] = {};
|
|
|
b42f0a |
socklen_t len = sizeof(address);
|
|
|
b42f0a |
int res = ::accept(sockId, (struct sockaddr*)address, &len);
|
|
|
b42f0a |
assert(len < sizeof(address));
|
|
|
b42f0a |
if (res >= 0)
|
|
|
b42f0a |
if (Connection *conn = onConnect(address, len))
|
|
|
b42f0a |
if (!conn->open(*protocol, address, len, res, this))
|
|
|
b42f0a |
onDisconnect(conn, true);
|
|
|
b42f0a |
}
|
|
|
b42f0a |
}
|
|
|
71057f |
}
|
|
|
71057f |
|
|
|
71057f |
|
|
|
b42f0a |
|
|
|
51b3f0 |
Connection* Server::onConnect(const void*, size_t) { return nullptr; }
|
|
|
71057f |
void Server::onDisconnect(Connection*, bool) { }
|
|
|
71057f |
|