Newer
Older
#include <ftl/uri.hpp>
#include <ftl/net/listener.hpp>
#include <ftl/net/socket.hpp>
#include <ftl/net/protocol.hpp>
#include <iostream>
#ifndef WIN32
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#endif
#ifdef WIN32
#include <windows.h>
#include <winsock.h>
typedef int socklen_t;
#define MSG_WAITALL 0
#endif
using namespace ftl;
using ftl::net::Listener;
int tcpListen(URI &uri) {
int ssock;
//std::cerr << "TCP Listen: " << uri.getHost() << " : " << uri.getPort() << std::endl;
#ifdef WIN32
WSAData wsaData;
//If Win32 then load winsock
if (WSAStartup(MAKEWORD(1,1), &wsaData) != 0) {
return INVALID_SOCKET;
}
#endif
ssock = socket(AF_INET, SOCK_STREAM, 0);
if (ssock == INVALID_SOCKET) {
return INVALID_SOCKET;
}
int enable = 1;
if (setsockopt(ssock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0)
LOG(ERROR) << "setsockopt(SO_REUSEADDR) failed";
//Specify listen port and address
sockaddr_in slocalAddr;
slocalAddr.sin_family = AF_INET;
slocalAddr.sin_addr.s_addr = htonl(INADDR_ANY); // TODO, use that given in URI
slocalAddr.sin_port = htons(uri.getPort());
int rc = ::bind(ssock, (struct sockaddr*)&slocalAddr, sizeof(slocalAddr));
if (rc == SOCKET_ERROR) {
#ifndef WIN32
close(ssock);
#else
closesocket(ssock);
#endif
ssock = INVALID_SOCKET;
LOG(ERROR) << "Could not bind to " << uri.getBaseURI();
return INVALID_SOCKET;
}
//Attempt to start listening for connection requests.
rc = ::listen(ssock, 1);
if (rc == SOCKET_ERROR) {
#ifndef WIN32
close(ssock);
#else
closesocket(ssock);
#endif
ssock = INVALID_SOCKET;
LOG(ERROR) << "Could not listen on " << uri.getBaseURI();
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
return INVALID_SOCKET;
}
return ssock;
}
int wsListen(URI &uri) {
return INVALID_SOCKET;
}
Listener::Listener(const char *pUri) {
URI uri(pUri);
descriptor_ = INVALID_SOCKET;
if (uri.getProtocol() == URI::SCHEME_TCP) {
descriptor_ = tcpListen(uri);
std::cout << "Listening: " << pUri << " - " << descriptor_ << std::endl;
} else if (uri.getProtocol() == URI::SCHEME_WS) {
descriptor_ = wsListen(uri);
} else {
}
}
Listener::~Listener() {
// Close the socket.
close();
}
void Listener::connection(shared_ptr<Socket> &s) {
if (default_proto_) {
s->setProtocol(default_proto_);
}
for (auto h : handler_connect_) h(s);
}
void Listener::close() {
#ifndef WIN32
::close(descriptor_);
#else
closesocket(descriptor_);
#endif
descriptor_ = INVALID_SOCKET;
// Attempt auto reconnect?