[DEV] first implementation of windows socket (missing read)
This commit is contained in:
parent
5cb8ea40e3
commit
a979e33401
@ -208,21 +208,21 @@ namespace etk {
|
|||||||
}
|
}
|
||||||
template <>
|
template <>
|
||||||
bool from_string<enum enet::HTTPReqType>(enum enet::HTTPReqType& _variableRet, const std::string& _value) {
|
bool from_string<enum enet::HTTPReqType>(enum enet::HTTPReqType& _variableRet, const std::string& _value) {
|
||||||
_variableRet = enet::HTTPReqType::GET;
|
_variableRet = enet::HTTPReqType::HTTP_GET;
|
||||||
if (_value == "GET") {
|
if (_value == "GET") {
|
||||||
_variableRet = enet::HTTPReqType::GET;
|
_variableRet = enet::HTTPReqType::HTTP_GET;
|
||||||
return true;
|
return true;
|
||||||
} else if (_value == "HEAD") {
|
} else if (_value == "HEAD") {
|
||||||
_variableRet = enet::HTTPReqType::HEAD;
|
_variableRet = enet::HTTPReqType::HTTP_HEAD;
|
||||||
return true;
|
return true;
|
||||||
} else if (_value == "POST") {
|
} else if (_value == "POST") {
|
||||||
_variableRet = enet::HTTPReqType::POST;
|
_variableRet = enet::HTTPReqType::HTTP_POST;
|
||||||
return true;
|
return true;
|
||||||
} else if (_value == "PUT") {
|
} else if (_value == "PUT") {
|
||||||
_variableRet = enet::HTTPReqType::PUT;
|
_variableRet = enet::HTTPReqType::HTTP_PUT;
|
||||||
return true;
|
return true;
|
||||||
} else if (_value == "DELETE") {
|
} else if (_value == "DELETE") {
|
||||||
_variableRet = enet::HTTPReqType::DELETE;
|
_variableRet = enet::HTTPReqType::HTTP_DELETE;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -230,11 +230,11 @@ namespace etk {
|
|||||||
template <>
|
template <>
|
||||||
std::string to_string<enum enet::HTTPReqType>(const enum enet::HTTPReqType& _value) {
|
std::string to_string<enum enet::HTTPReqType>(const enum enet::HTTPReqType& _value) {
|
||||||
switch (_value) {
|
switch (_value) {
|
||||||
case enet::HTTPReqType::GET: return "GET";
|
case enet::HTTPReqType::HTTP_GET: return "GET";
|
||||||
case enet::HTTPReqType::HEAD: return "HEAD";
|
case enet::HTTPReqType::HTTP_HEAD: return "HEAD";
|
||||||
case enet::HTTPReqType::POST: return "POST";
|
case enet::HTTPReqType::HTTP_POST: return "POST";
|
||||||
case enet::HTTPReqType::PUT: return "PUT";
|
case enet::HTTPReqType::HTTP_PUT: return "PUT";
|
||||||
case enet::HTTPReqType::DELETE: return "DELETE";
|
case enet::HTTPReqType::HTTP_DELETE: return "DELETE";
|
||||||
}
|
}
|
||||||
return "UNKNOW";
|
return "UNKNOW";
|
||||||
}
|
}
|
||||||
|
@ -156,11 +156,11 @@ namespace enet {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
enum class HTTPReqType {
|
enum class HTTPReqType {
|
||||||
GET,
|
HTTP_GET,
|
||||||
HEAD,
|
HTTP_HEAD,
|
||||||
POST,
|
HTTP_POST,
|
||||||
PUT,
|
HTTP_PUT,
|
||||||
DELETE,
|
HTTP_DELETE,
|
||||||
};
|
};
|
||||||
std::ostream& operator <<(std::ostream& _os, enum enet::HTTPReqType _obj);
|
std::ostream& operator <<(std::ostream& _os, enum enet::HTTPReqType _obj);
|
||||||
class HttpRequest : public HttpHeader {
|
class HttpRequest : public HttpHeader {
|
||||||
@ -169,7 +169,7 @@ namespace enet {
|
|||||||
enum HTTPReqType m_req;
|
enum HTTPReqType m_req;
|
||||||
std::string m_uri;
|
std::string m_uri;
|
||||||
public:
|
public:
|
||||||
HttpRequest(enum enet::HTTPReqType _type=enet::HTTPReqType::GET);
|
HttpRequest(enum enet::HTTPReqType _type=enet::HTTPReqType::HTTP_GET);
|
||||||
void display() const;
|
void display() const;
|
||||||
std::string generate() const;
|
std::string generate() const;
|
||||||
void setType(enum enet::HTTPReqType _value) {
|
void setType(enum enet::HTTPReqType _value) {
|
||||||
|
138
enet/Tcp.cpp
138
enet/Tcp.cpp
@ -7,7 +7,6 @@
|
|||||||
#include <enet/debug.hpp>
|
#include <enet/debug.hpp>
|
||||||
#include <enet/Tcp.hpp>
|
#include <enet/Tcp.hpp>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <netdb.h>
|
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@ -20,6 +19,7 @@
|
|||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
|
#include <netdb.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool enet::Tcp::setTCPNoDelay(bool _enabled) {
|
bool enet::Tcp::setTCPNoDelay(bool _enabled) {
|
||||||
@ -35,32 +35,48 @@ bool enet::Tcp::setTCPNoDelay(bool _enabled) {
|
|||||||
|
|
||||||
|
|
||||||
enet::Tcp::Tcp() :
|
enet::Tcp::Tcp() :
|
||||||
|
#ifdef __TARGET_OS__Windows
|
||||||
|
m_socketId(INVALID_SOCKET),
|
||||||
|
#else
|
||||||
m_socketId(-1),
|
m_socketId(-1),
|
||||||
|
#endif
|
||||||
m_name(),
|
m_name(),
|
||||||
m_status(status::error) {
|
m_status(status::error) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enet::Tcp::Tcp(int32_t _idSocket, const std::string& _name) :
|
#ifdef __TARGET_OS__Windows
|
||||||
|
enet::Tcp::Tcp(SOCKET _idSocket, const std::string& _name) :
|
||||||
|
#else
|
||||||
|
enet::Tcp::Tcp(int32_t _idSocket, const std::string& _name) :
|
||||||
|
#endif
|
||||||
m_socketId(_idSocket),
|
m_socketId(_idSocket),
|
||||||
m_name(_name),
|
m_name(_name),
|
||||||
m_status(status::link) {
|
m_status(status::link) {
|
||||||
//Initialize the pollfd structure
|
//Initialize the pollfd structure
|
||||||
memset(&m_fds[0], 0 , sizeof(m_fds));
|
memset(&m_fds[0], 0 , sizeof(m_fds));
|
||||||
//Set up the initial listening socket
|
//Set up the initial listening socket
|
||||||
m_fds[0].fd = _idSocket;
|
#ifndef __TARGET_OS__Windows
|
||||||
m_fds[0].events = POLLIN | POLLERR;
|
m_fds[0].fd = _idSocket;
|
||||||
|
m_fds[0].events = POLLIN | POLLERR;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
enet::Tcp::Tcp(Tcp&& _obj) :
|
enet::Tcp::Tcp(Tcp&& _obj) :
|
||||||
m_socketId(_obj.m_socketId),
|
m_socketId(_obj.m_socketId),
|
||||||
m_name(_obj.m_name),
|
m_name(_obj.m_name),
|
||||||
m_status(_obj.m_status) {
|
m_status(_obj.m_status) {
|
||||||
_obj.m_socketId = -1;
|
#ifdef __TARGET_OS__Windows
|
||||||
|
_obj.m_socketId = INVALID_SOCKET;
|
||||||
|
#else
|
||||||
|
_obj.m_socketId = -1;
|
||||||
|
#endif
|
||||||
_obj.m_name = "";
|
_obj.m_name = "";
|
||||||
_obj.m_status = status::error;
|
_obj.m_status = status::error;
|
||||||
m_fds[0] = _obj.m_fds[0];
|
#ifndef __TARGET_OS__Windows
|
||||||
memset(&m_fds[0], 0 , sizeof(m_fds));
|
m_fds[0] = _obj.m_fds[0];
|
||||||
|
memset(&m_fds[0], 0 , sizeof(m_fds));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
enet::Tcp::~Tcp() {
|
enet::Tcp::~Tcp() {
|
||||||
@ -70,20 +86,30 @@ enet::Tcp::~Tcp() {
|
|||||||
enet::Tcp& enet::Tcp::operator = (enet::Tcp&& _obj) {
|
enet::Tcp& enet::Tcp::operator = (enet::Tcp&& _obj) {
|
||||||
unlink();
|
unlink();
|
||||||
m_socketId = _obj.m_socketId;
|
m_socketId = _obj.m_socketId;
|
||||||
_obj.m_socketId = -1;
|
#ifdef __TARGET_OS__Windows
|
||||||
|
_obj.m_socketId = INVALID_SOCKET;
|
||||||
|
#else
|
||||||
|
_obj.m_socketId = -1;
|
||||||
|
#endif
|
||||||
m_name = _obj.m_name;
|
m_name = _obj.m_name;
|
||||||
_obj.m_name = "";
|
_obj.m_name = "";
|
||||||
m_status = _obj.m_status;
|
m_status = _obj.m_status;
|
||||||
_obj.m_status = status::error;
|
_obj.m_status = status::error;
|
||||||
m_fds[0] = _obj.m_fds[0];
|
#ifndef __TARGET_OS__Windows
|
||||||
memset(&m_fds[0], 0 , sizeof(m_fds));
|
m_fds[0] = _obj.m_fds[0];
|
||||||
|
memset(&m_fds[0], 0 , sizeof(m_fds));
|
||||||
|
#endif
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool enet::Tcp::unlink() {
|
bool enet::Tcp::unlink() {
|
||||||
if (m_socketId >= 0) {
|
if (m_socketId >= 0) {
|
||||||
ENET_INFO("Close socket (start)");
|
ENET_INFO("Close socket (start)");
|
||||||
shutdown(m_socketId, SHUT_RDWR);
|
#ifdef __TARGET_OS__Windows
|
||||||
|
shutdown(m_socketId, SD_BOTH);
|
||||||
|
#else
|
||||||
|
shutdown(m_socketId, SHUT_RDWR);
|
||||||
|
#endif
|
||||||
#ifdef __TARGET_OS__Windows
|
#ifdef __TARGET_OS__Windows
|
||||||
closesocket(m_socketId);
|
closesocket(m_socketId);
|
||||||
#else
|
#else
|
||||||
@ -103,50 +129,54 @@ int32_t enet::Tcp::read(void* _data, int32_t _maxLen) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
int32_t size = -1;
|
int32_t size = -1;
|
||||||
int nfds = 1;
|
|
||||||
// Initialize the timeout to 3 minutes. If no activity after 3 minutes this program will end. timeout value is based on milliseconds.
|
// Initialize the timeout to 3 minutes. If no activity after 3 minutes this program will end. timeout value is based on milliseconds.
|
||||||
int timeout = (3 * 60 * 1000);
|
int timeout = (3 * 60 * 1000);
|
||||||
// Call poll() and wait 3 minutes for it to complete.
|
#ifdef __TARGET_OS__Windows
|
||||||
int rc = poll(m_fds, nfds, timeout);
|
|
||||||
// Check to see if the poll call failed.
|
#else
|
||||||
if (rc < 0) {
|
int nfds = 1;
|
||||||
ENET_ERROR(" poll() failed");
|
// Call poll() and wait 3 minutes for it to complete.
|
||||||
return-1;
|
int rc = poll(m_fds, nfds, timeout);
|
||||||
}
|
// Check to see if the poll call failed.
|
||||||
// Check to see if the 3 minute time out expired.
|
if (rc < 0) {
|
||||||
if (rc == 0) {
|
ENET_ERROR(" poll() failed");
|
||||||
ENET_ERROR(" poll() timed out.\n");
|
return-1;
|
||||||
return -2;
|
}
|
||||||
}
|
// Check to see if the 3 minute time out expired.
|
||||||
bool closeConn = false;
|
if (rc == 0) {
|
||||||
// Receive all incoming data on this socket before we loop back and call poll again.
|
ENET_ERROR(" poll() timed out.\n");
|
||||||
// Receive data on this connection until the recv fails with EWOULDBLOCK.
|
return -2;
|
||||||
// If any other failure occurs, we will close the connection.
|
}
|
||||||
{
|
bool closeConn = false;
|
||||||
std::unique_lock<std::mutex> lock(m_mutex);
|
// Receive all incoming data on this socket before we loop back and call poll again.
|
||||||
//ENET_DEBUG("Read on socketid = " << m_fds[0].fd );
|
// Receive data on this connection until the recv fails with EWOULDBLOCK.
|
||||||
rc = recv(m_fds[0].fd, _data, _maxLen, 0);
|
// If any other failure occurs, we will close the connection.
|
||||||
}
|
{
|
||||||
if (rc < 0) {
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
if (errno != EWOULDBLOCK) {
|
//ENET_DEBUG("Read on socketid = " << m_fds[0].fd );
|
||||||
ENET_ERROR(" recv() failed");
|
rc = recv(m_fds[0].fd, _data, _maxLen, 0);
|
||||||
|
}
|
||||||
|
if (rc < 0) {
|
||||||
|
if (errno != EWOULDBLOCK) {
|
||||||
|
ENET_ERROR(" recv() failed");
|
||||||
|
closeConn = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Check to see if the connection has been closed by the client
|
||||||
|
if (rc == 0) {
|
||||||
|
ENET_INFO("Connection closed");
|
||||||
closeConn = true;
|
closeConn = true;
|
||||||
}
|
}
|
||||||
}
|
if (closeConn == false) {
|
||||||
// Check to see if the connection has been closed by the client
|
// Data was received
|
||||||
if (rc == 0) {
|
size = rc;
|
||||||
ENET_INFO("Connection closed");
|
} else {
|
||||||
closeConn = true;
|
// If the close_conn flag was turned on, we need to clean up this active connection.
|
||||||
}
|
// This clean up process includes removing the descriptor.
|
||||||
if (closeConn == false) {
|
ENET_DEBUG(" Set status at remote close ...");
|
||||||
// Data was received
|
m_status = status::linkRemoteClose;
|
||||||
size = rc;
|
}
|
||||||
} else {
|
#endif
|
||||||
// If the close_conn flag was turned on, we need to clean up this active connection.
|
|
||||||
// This clean up process includes removing the descriptor.
|
|
||||||
ENET_DEBUG(" Set status at remote close ...");
|
|
||||||
m_status = status::linkRemoteClose;
|
|
||||||
}
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,7 +190,11 @@ int32_t enet::Tcp::write(const void* _data, int32_t _len) {
|
|||||||
int32_t size;
|
int32_t size;
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(m_mutex);
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
size = ::write(m_socketId, _data, _len);
|
#ifdef __TARGET_OS__Windows
|
||||||
|
size = ::send(m_socketId, (const char *)_data, _len, 0);
|
||||||
|
#else
|
||||||
|
size = ::write(m_socketId, _data, _len);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
if ( size != _len
|
if ( size != _len
|
||||||
&& errno != 0) {
|
&& errno != 0) {
|
||||||
|
@ -30,7 +30,11 @@ namespace enet {
|
|||||||
std::mutex m_mutex;
|
std::mutex m_mutex;
|
||||||
public:
|
public:
|
||||||
Tcp();
|
Tcp();
|
||||||
Tcp(int32_t _idSocket, const std::string& _name);
|
#ifdef __TARGET_OS__Windows
|
||||||
|
Tcp(SOCKET _idSocket, const std::string& _name);
|
||||||
|
#else
|
||||||
|
Tcp(int32_t _idSocket, const std::string& _name);
|
||||||
|
#endif
|
||||||
// move constructor
|
// move constructor
|
||||||
Tcp(Tcp&& _obj);
|
Tcp(Tcp&& _obj);
|
||||||
// Move operator;
|
// Move operator;
|
||||||
|
@ -7,9 +7,8 @@
|
|||||||
#include <enet/debug.hpp>
|
#include <enet/debug.hpp>
|
||||||
#include <enet/Tcp.hpp>
|
#include <enet/Tcp.hpp>
|
||||||
#include <enet/TcpClient.hpp>
|
#include <enet/TcpClient.hpp>
|
||||||
|
#include <enet/enet.hpp>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@ -18,7 +17,8 @@
|
|||||||
#ifdef __TARGET_OS__Windows
|
#ifdef __TARGET_OS__Windows
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#include <sys/socket.h>
|
#include <netinet/in.h>
|
||||||
|
#include <netdb.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enet::Tcp enet::connectTcpClient(uint8_t _ip1, uint8_t _ip2, uint8_t _ip3, uint8_t _ip4, uint16_t _port, uint32_t _numberRetry) {
|
enet::Tcp enet::connectTcpClient(uint8_t _ip1, uint8_t _ip2, uint8_t _ip3, uint8_t _ip4, uint16_t _port, uint32_t _numberRetry) {
|
||||||
@ -32,56 +32,133 @@ enet::Tcp enet::connectTcpClient(uint8_t _ip1, uint8_t _ip2, uint8_t _ip3, uint8
|
|||||||
tmpname += etk::to_string(_ip4);
|
tmpname += etk::to_string(_ip4);
|
||||||
return std::move(enet::connectTcpClient(tmpname, _port, _numberRetry));
|
return std::move(enet::connectTcpClient(tmpname, _port, _numberRetry));
|
||||||
}
|
}
|
||||||
enet::Tcp enet::connectTcpClient(const std::string& _hostname, uint16_t _port, uint32_t _numberRetry) {
|
|
||||||
int32_t socketId = -1;
|
#ifdef __TARGET_OS__Windows
|
||||||
ENET_INFO("Start connection on " << _hostname << ":" << _port);
|
enet::Tcp enet::connectTcpClient(const std::string& _hostname, uint16_t _port, uint32_t _numberRetry) {
|
||||||
for(int32_t iii=0; iii<_numberRetry ;iii++) {
|
if (enet::isInit() == false) {
|
||||||
// open in Socket normal mode
|
ENET_ERROR("Need call enet::init(...) before accessing to the socket");
|
||||||
socketId = socket(AF_INET, SOCK_STREAM, 0);
|
return std::move(enet::Tcp());
|
||||||
if (socketId < 0) {
|
}
|
||||||
ENET_ERROR("ERROR while opening socket : errno=" << errno << "," << strerror(errno));
|
SOCKET socketId = INVALID_SOCKET;
|
||||||
usleep(200000);
|
ENET_INFO("Start connection on " << _hostname << ":" << _port);
|
||||||
continue;
|
for(int32_t iii=0; iii<_numberRetry ;iii++) {
|
||||||
}
|
// open in Socket normal mode
|
||||||
ENET_INFO("Try connect on socket ... (" << iii+1 << "/" << _numberRetry << ")");
|
socketId = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
struct sockaddr_in servAddr;
|
if (socketId < 0) {
|
||||||
struct hostent* server = gethostbyname(_hostname.c_str());
|
ENET_ERROR("ERROR while opening socket : errno=" << errno << "," << strerror(errno));
|
||||||
if (server == nullptr) {
|
usleep(200000);
|
||||||
ENET_ERROR("ERROR, no such host : " << _hostname);
|
continue;
|
||||||
usleep(200000);
|
}
|
||||||
continue;
|
ENET_INFO("Try connect on socket ... (" << iii+1 << "/" << _numberRetry << ")");
|
||||||
}
|
|
||||||
bzero((char *) &servAddr, sizeof(servAddr));
|
struct addrinfo hints;
|
||||||
servAddr.sin_family = AF_INET;
|
memset(&hints, 0, sizeof(hints));
|
||||||
bcopy((char *)server->h_addr, (char *)&servAddr.sin_addr.s_addr, server->h_length);
|
hints.ai_family = AF_UNSPEC;
|
||||||
servAddr.sin_port = htons(_port);
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
ENET_INFO("Start connexion ...");
|
hints.ai_protocol = IPPROTO_TCP;
|
||||||
if (connect(socketId, (struct sockaddr *)&servAddr,sizeof(servAddr)) != 0) {
|
|
||||||
if(errno != EINPROGRESS) {
|
// Resolve the server address and port
|
||||||
if( errno != ENOENT
|
struct addrinfo* result = nullptr;
|
||||||
&& errno != EAGAIN
|
std::string portValue = etk::to_string(_port);
|
||||||
&& errno != ECONNREFUSED) {
|
int iResult = getaddrinfo(_hostname.c_str(), portValue.c_str(), &hints, &result);
|
||||||
ENET_ERROR("ERROR connecting on : errno=" << errno << "," << strerror(errno));
|
if (iResult != 0) {
|
||||||
}
|
ENET_ERROR("getaddrinfo failed with error: " << iResult);
|
||||||
#ifdef __TARGET_OS__Windows
|
usleep(200000);
|
||||||
closesocket(socketId);
|
continue;
|
||||||
#else
|
}
|
||||||
close(socketId);
|
|
||||||
#endif
|
// Attempt to connect to an address until one succeeds
|
||||||
socketId = -1;
|
for(struct addrinfo* ptr=result;
|
||||||
}
|
ptr != nullptr;
|
||||||
ENET_ERROR("ERROR connecting, maybe retry ... errno=" << errno << "," << strerror(errno));
|
ptr=ptr->ai_next) {
|
||||||
usleep(500000);
|
// Create a SOCKET for connecting to server
|
||||||
continue;
|
socketId = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
|
||||||
}
|
if (socketId == INVALID_SOCKET) {
|
||||||
// if we are here ==> then the connextion is done corectly ...
|
ENET_ERROR("socket failed with error: " << WSAGetLastError());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (socketId<0) {
|
// Connect to server.
|
||||||
ENET_ERROR("ERROR connecting ... (after all try)");
|
iResult = connect(socketId, ptr->ai_addr, (int)ptr->ai_addrlen);
|
||||||
return std::move(enet::Tcp());
|
if (iResult == SOCKET_ERROR) {
|
||||||
}
|
closesocket(socketId);
|
||||||
ENET_DEBUG("Connection done");
|
socketId = INVALID_SOCKET;
|
||||||
return std::move(enet::Tcp(socketId, _hostname + ":" + etk::to_string(_port)));
|
continue;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
freeaddrinfo(result);
|
||||||
|
|
||||||
|
if (socketId == INVALID_SOCKET) {
|
||||||
|
ENET_ERROR("Unable to connect to server!");
|
||||||
|
WSACleanup();
|
||||||
|
usleep(200000);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (socketId == INVALID_SOCKET) {
|
||||||
|
ENET_ERROR("ERROR connecting ... (after all try)");
|
||||||
|
return std::move(enet::Tcp());
|
||||||
|
}
|
||||||
|
ENET_DEBUG("Connection done");
|
||||||
|
return std::move(enet::Tcp(socketId, _hostname + ":" + etk::to_string(_port)));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#include <sys/socket.h>
|
||||||
|
enet::Tcp enet::connectTcpClient(const std::string& _hostname, uint16_t _port, uint32_t _numberRetry) {
|
||||||
|
if (enet::isInit() == false) {
|
||||||
|
ENET_ERROR("Need call enet::init(...) before accessing to the socket");
|
||||||
|
return std::move(enet::Tcp());
|
||||||
|
}
|
||||||
|
int32_t socketId = -1;
|
||||||
|
ENET_INFO("Start connection on " << _hostname << ":" << _port);
|
||||||
|
for(int32_t iii=0; iii<_numberRetry ;iii++) {
|
||||||
|
// open in Socket normal mode
|
||||||
|
socketId = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
if (socketId < 0) {
|
||||||
|
ENET_ERROR("ERROR while opening socket : errno=" << errno << "," << strerror(errno));
|
||||||
|
usleep(200000);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ENET_INFO("Try connect on socket ... (" << iii+1 << "/" << _numberRetry << ")");
|
||||||
|
struct sockaddr_in servAddr;
|
||||||
|
struct hostent* server = gethostbyname(_hostname.c_str());
|
||||||
|
if (server == nullptr) {
|
||||||
|
ENET_ERROR("ERROR, no such host : " << _hostname);
|
||||||
|
usleep(200000);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
bzero((char *) &servAddr, sizeof(servAddr));
|
||||||
|
servAddr.sin_family = AF_INET;
|
||||||
|
bcopy((char *)server->h_addr, (char *)&servAddr.sin_addr.s_addr, server->h_length);
|
||||||
|
servAddr.sin_port = htons(_port);
|
||||||
|
ENET_INFO("Start connexion ...");
|
||||||
|
if (connect(socketId, (struct sockaddr *)&servAddr,sizeof(servAddr)) != 0) {
|
||||||
|
if(errno != EINPROGRESS) {
|
||||||
|
if( errno != ENOENT
|
||||||
|
&& errno != EAGAIN
|
||||||
|
&& errno != ECONNREFUSED) {
|
||||||
|
ENET_ERROR("ERROR connecting on : errno=" << errno << "," << strerror(errno));
|
||||||
|
}
|
||||||
|
#ifdef __TARGET_OS__Windows
|
||||||
|
closesocket(socketId);
|
||||||
|
#else
|
||||||
|
close(socketId);
|
||||||
|
#endif
|
||||||
|
socketId = -1;
|
||||||
|
}
|
||||||
|
ENET_ERROR("ERROR connecting, maybe retry ... errno=" << errno << "," << strerror(errno));
|
||||||
|
usleep(500000);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// if we are here ==> then the connextion is done corectly ...
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (socketId<0) {
|
||||||
|
ENET_ERROR("ERROR connecting ... (after all try)");
|
||||||
|
return std::move(enet::Tcp());
|
||||||
|
}
|
||||||
|
ENET_DEBUG("Connection done");
|
||||||
|
return std::move(enet::Tcp(socketId, _hostname + ":" + etk::to_string(_port)));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <enet/debug.hpp>
|
#include <enet/debug.hpp>
|
||||||
#include <enet/Tcp.hpp>
|
#include <enet/Tcp.hpp>
|
||||||
#include <enet/TcpServer.hpp>
|
#include <enet/TcpServer.hpp>
|
||||||
|
#include <enet/enet.hpp>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -61,43 +62,109 @@ void enet::TcpServer::setPort(uint16_t _port) {
|
|||||||
m_port = _port;
|
m_port = _port;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool enet::TcpServer::link() {
|
#ifdef __TARGET_OS__Windows
|
||||||
ENET_INFO("Start connection on " << m_host << ":" << m_port);
|
bool enet::TcpServer::link() {
|
||||||
// open in Socket normal mode
|
if (enet::isInit() == false) {
|
||||||
m_socketId = socket(AF_INET, SOCK_STREAM, 0);
|
ENET_ERROR("Need call enet::init(...) before accessing to the socket");
|
||||||
if (m_socketId < 0) {
|
return false;
|
||||||
ENET_ERROR("ERROR while opening socket : errno=" << errno << "," << strerror(errno));
|
}
|
||||||
return false;
|
ENET_INFO("Start connection on " << m_host << ":" << m_port);
|
||||||
}
|
|
||||||
// set the reuse of the socket if previously opened :
|
struct addrinfo *result = nullptr;
|
||||||
int sockOpt = 1;
|
struct addrinfo hints;
|
||||||
if(setsockopt(m_socketId, SOL_SOCKET, SO_REUSEADDR, (const char*)&sockOpt, sizeof(int)) != 0) {
|
ZeroMemory(&hints, sizeof(hints));
|
||||||
ENET_ERROR("ERROR while configuring socket re-use : errno=" << errno << "," << strerror(errno));
|
hints.ai_family = AF_INET;
|
||||||
return false;
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
}
|
hints.ai_protocol = IPPROTO_TCP;
|
||||||
// clear all
|
hints.ai_flags = AI_PASSIVE;
|
||||||
struct sockaddr_in servAddr;
|
|
||||||
bzero((char *) &servAddr, sizeof(servAddr));
|
// Resolve the server address and port
|
||||||
servAddr.sin_family = AF_INET;
|
std::string portValue = etk::to_string(m_port);
|
||||||
servAddr.sin_addr.s_addr = INADDR_ANY;
|
int iResult = getaddrinfo(nullptr, portValue.c_str(), &hints, &result);
|
||||||
servAddr.sin_port = htons(m_port);
|
if (iResult != 0) {
|
||||||
ENET_INFO("Start binding Socket ... (can take some time ...)");
|
ENET_ERROR("getaddrinfo failed with error: " << iResult);
|
||||||
if (bind(m_socketId, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0) {
|
return 1;
|
||||||
ENET_ERROR("ERROR on binding errno=" << errno << "," << strerror(errno));
|
}
|
||||||
#ifdef __TARGET_OS__Windows
|
|
||||||
|
// open in Socket normal mode
|
||||||
|
m_socketId = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
|
||||||
|
if (m_socketId != INVALID_SOCKET) {
|
||||||
|
ENET_ERROR("ERROR while opening socket : errno=" << errno << "," << strerror(errno));
|
||||||
|
freeaddrinfo(result);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// set the reuse of the socket if previously opened :
|
||||||
|
int sockOpt = 1;
|
||||||
|
if(setsockopt(m_socketId, SOL_SOCKET, SO_REUSEADDR, (const char*)&sockOpt, sizeof(int)) != 0) {
|
||||||
|
ENET_ERROR("ERROR while configuring socket re-use : errno=" << errno << "," << strerror(errno));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ENET_INFO("Start binding Socket ... (can take some time ...)");
|
||||||
|
if (bind(m_socketId, result->ai_addr, (int)result->ai_addrlen) == SOCKET_ERROR) {
|
||||||
|
ENET_ERROR("ERROR on binding errno=" << WSAGetLastError());
|
||||||
|
freeaddrinfo(result);
|
||||||
closesocket(m_socketId);
|
closesocket(m_socketId);
|
||||||
#else
|
m_socketId = INVALID_SOCKET;
|
||||||
close(m_socketId);
|
return false;
|
||||||
#endif
|
}
|
||||||
m_socketId = -1;
|
return true;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return true;
|
#else
|
||||||
}
|
bool enet::TcpServer::link() {
|
||||||
|
if (enet::isInit() == false) {
|
||||||
|
ENET_ERROR("Need call enet::init(...) before accessing to the socket");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ENET_INFO("Start connection on " << m_host << ":" << m_port);
|
||||||
|
// open in Socket normal mode
|
||||||
|
m_socketId = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
if (m_socketId < 0) {
|
||||||
|
ENET_ERROR("ERROR while opening socket : errno=" << errno << "," << strerror(errno));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// set the reuse of the socket if previously opened :
|
||||||
|
int sockOpt = 1;
|
||||||
|
if(setsockopt(m_socketId, SOL_SOCKET, SO_REUSEADDR, (const char*)&sockOpt, sizeof(int)) != 0) {
|
||||||
|
ENET_ERROR("ERROR while configuring socket re-use : errno=" << errno << "," << strerror(errno));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// clear all
|
||||||
|
struct sockaddr_in servAddr;
|
||||||
|
bzero((char *) &servAddr, sizeof(servAddr));
|
||||||
|
servAddr.sin_family = AF_INET;
|
||||||
|
servAddr.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
servAddr.sin_port = htons(m_port);
|
||||||
|
ENET_INFO("Start binding Socket ... (can take some time ...)");
|
||||||
|
if (bind(m_socketId, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0) {
|
||||||
|
ENET_ERROR("ERROR on binding errno=" << errno << "," << strerror(errno));
|
||||||
|
#ifdef __TARGET_OS__Windows
|
||||||
|
closesocket(m_socketId);
|
||||||
|
m_socketId = INVALID_SOCKET;
|
||||||
|
#else
|
||||||
|
close(m_socketId);
|
||||||
|
m_socketId = -1;
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
enet::Tcp enet::TcpServer::waitNext() {
|
enet::Tcp enet::TcpServer::waitNext() {
|
||||||
|
if (enet::isInit() == false) {
|
||||||
|
ENET_ERROR("Need call enet::init(...) before accessing to the socket");
|
||||||
|
return std::move(enet::Tcp());
|
||||||
|
}
|
||||||
ENET_INFO("End binding Socket ... (start listen)");
|
ENET_INFO("End binding Socket ... (start listen)");
|
||||||
listen(m_socketId,1); // 1 is for the number of connection at the same time ...
|
#ifdef __TARGET_OS__Windows
|
||||||
|
int ret = listen(m_socketId, SOMAXCONN);
|
||||||
|
if (ret == SOCKET_ERROR) {
|
||||||
|
ENET_ERROR("listen failed with error: " << WSAGetLastError());
|
||||||
|
return enet::Tcp();;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
listen(m_socketId, 1); // 1 is for the number of connection at the same time ...
|
||||||
|
#endif
|
||||||
ENET_INFO("End listen Socket ... (start accept)");
|
ENET_INFO("End listen Socket ... (start accept)");
|
||||||
struct sockaddr_in clientAddr;
|
struct sockaddr_in clientAddr;
|
||||||
socklen_t clilen = sizeof(clientAddr);
|
socklen_t clilen = sizeof(clientAddr);
|
||||||
@ -106,10 +173,12 @@ enet::Tcp enet::TcpServer::waitNext() {
|
|||||||
ENET_ERROR("ERROR on accept errno=" << errno << "," << strerror(errno));
|
ENET_ERROR("ERROR on accept errno=" << errno << "," << strerror(errno));
|
||||||
#ifdef __TARGET_OS__Windows
|
#ifdef __TARGET_OS__Windows
|
||||||
closesocket(m_socketId);
|
closesocket(m_socketId);
|
||||||
|
m_socketId = INVALID_SOCKET;
|
||||||
#else
|
#else
|
||||||
close(m_socketId);
|
close(m_socketId);
|
||||||
|
m_socketId = -1;
|
||||||
#endif
|
#endif
|
||||||
m_socketId = -1;
|
|
||||||
return enet::Tcp();
|
return enet::Tcp();
|
||||||
}
|
}
|
||||||
ENET_INFO("End configuring Socket ... Find New one");
|
ENET_INFO("End configuring Socket ... Find New one");
|
||||||
@ -118,14 +187,18 @@ enet::Tcp enet::TcpServer::waitNext() {
|
|||||||
|
|
||||||
|
|
||||||
bool enet::TcpServer::unlink() {
|
bool enet::TcpServer::unlink() {
|
||||||
if (m_socketId >= 0) {
|
#ifdef __TARGET_OS__Windows
|
||||||
ENET_INFO(" close server socket");
|
if (m_socketId != INVALID_SOCKET) {
|
||||||
#ifdef __TARGET_OS__Windows
|
ENET_INFO(" close server socket");
|
||||||
closesocket(m_socketId);
|
closesocket(m_socketId);
|
||||||
#else
|
m_socketId = INVALID_SOCKET;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (m_socketId >= 0) {
|
||||||
|
ENET_INFO(" close server socket");
|
||||||
close(m_socketId);
|
close(m_socketId);
|
||||||
#endif
|
m_socketId = -1;
|
||||||
m_socketId = -1;
|
}
|
||||||
}
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ void enet::WebSocket::start(const std::string& _uri, const std::vector<std::stri
|
|||||||
}
|
}
|
||||||
m_interface->start();
|
m_interface->start();
|
||||||
if (m_interface->isServer() == false) {
|
if (m_interface->isServer() == false) {
|
||||||
enet::HttpRequest req(enet::HTTPReqType::GET);
|
enet::HttpRequest req(enet::HTTPReqType::HTTP_GET);
|
||||||
req.setProtocol(enet::HTTPProtocol::http_1_1);
|
req.setProtocol(enet::HTTPProtocol::http_1_1);
|
||||||
req.setUri(_uri);
|
req.setUri(_uri);
|
||||||
req.setKey("Upgrade", "websocket");
|
req.setKey("Upgrade", "websocket");
|
||||||
@ -342,7 +342,7 @@ void enet::WebSocket::onReceiveRequest(const enet::HttpRequest& _data) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_data.display();
|
_data.display();
|
||||||
if (_data.getType() != enet::HTTPReqType::GET) {
|
if (_data.getType() != enet::HTTPReqType::HTTP_GET) {
|
||||||
enet::HttpAnswer answer(enet::HTTPAnswerCode::c400_badRequest, "support only GET");
|
enet::HttpAnswer answer(enet::HTTPAnswerCode::c400_badRequest, "support only GET");
|
||||||
answer.setProtocol(enet::HTTPProtocol::http_1_1);
|
answer.setProtocol(enet::HTTPProtocol::http_1_1);
|
||||||
answer.setKey("Connection", "close");
|
answer.setKey("Connection", "close");
|
||||||
|
54
enet/enet.cpp
Normal file
54
enet/enet.cpp
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/** @file
|
||||||
|
* @author Edouard DUPIN
|
||||||
|
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||||
|
* @license APACHE v2.0 (see license file)
|
||||||
|
*/
|
||||||
|
#include <enet/enet.hpp>
|
||||||
|
#include <enet/debug.hpp>
|
||||||
|
|
||||||
|
static bool& getInitSatatus() {
|
||||||
|
static bool isInit = false;
|
||||||
|
return isInit;
|
||||||
|
}
|
||||||
|
#ifdef __TARGET_OS__Windows
|
||||||
|
#include <winsock2.h>
|
||||||
|
#pragma comment(lib, "ws2_32.lib")
|
||||||
|
|
||||||
|
WSADATA wsaData;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void enet::init(int _argc, const char** _argv) {
|
||||||
|
for (int32_t iii=0; iii<_argc; ++iii) {
|
||||||
|
std::string value = _argv[iii];
|
||||||
|
if (etk::start_with(value, "--enet") == true) {
|
||||||
|
ENET_ERROR("Unknow parameter type: '" << value << "'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (getInitSatatus() == false) {
|
||||||
|
#ifdef __TARGET_OS__Windows
|
||||||
|
// Initialize Winsock
|
||||||
|
int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
|
||||||
|
if (iResult != 0) {
|
||||||
|
ENET_ERROR("WSAStartup failed with error: " << iResult);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
getInitSatatus() = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void unInit() {
|
||||||
|
if (getInitSatatus() == false) {
|
||||||
|
ENET_ERROR("Request UnInit of enent already done ...");
|
||||||
|
} else {
|
||||||
|
#ifdef __TARGET_OS__Windows
|
||||||
|
WSACleanup();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
getInitSatatus() = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool isInit() {
|
||||||
|
return getInitSatatus();
|
||||||
|
}
|
||||||
|
|
@ -15,6 +15,20 @@
|
|||||||
* @brief Main esvg namespace
|
* @brief Main esvg namespace
|
||||||
*/
|
*/
|
||||||
namespace enet {
|
namespace enet {
|
||||||
|
/**
|
||||||
|
* @brief Initialize enet
|
||||||
|
* @param[in] _argc Number of argument list
|
||||||
|
* @param[in] _argv List of arguments
|
||||||
|
*/
|
||||||
|
void init(int _argc, const char** _argv);
|
||||||
|
/**
|
||||||
|
* @brief un-Initialize enet
|
||||||
|
*/
|
||||||
|
void unInit();
|
||||||
|
/**
|
||||||
|
* @brief Check if the library is initialized
|
||||||
|
* @return bool value to chek if initialize ot not
|
||||||
|
*/
|
||||||
|
bool isInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ def configure(target, my_module):
|
|||||||
my_module.add_path(".")
|
my_module.add_path(".")
|
||||||
my_module.add_src_file([
|
my_module.add_src_file([
|
||||||
'enet/debug.cpp',
|
'enet/debug.cpp',
|
||||||
|
'enet/enet.cpp',
|
||||||
'enet/Udp.cpp',
|
'enet/Udp.cpp',
|
||||||
'enet/Tcp.cpp',
|
'enet/Tcp.cpp',
|
||||||
'enet/TcpServer.cpp',
|
'enet/TcpServer.cpp',
|
||||||
@ -51,6 +52,8 @@ def configure(target, my_module):
|
|||||||
'enet/Ftp.hpp',
|
'enet/Ftp.hpp',
|
||||||
'enet/WebSocket.hpp',
|
'enet/WebSocket.hpp',
|
||||||
])
|
])
|
||||||
|
if "Windows" in target.get_type():
|
||||||
|
my_module.add_depend("ws2");
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ namespace appl {
|
|||||||
void onReceiveHeader(enet::HttpServer* _interface, const enet::HttpRequest& _data) {
|
void onReceiveHeader(enet::HttpServer* _interface, const enet::HttpRequest& _data) {
|
||||||
TEST_INFO("Receive Header data:");
|
TEST_INFO("Receive Header data:");
|
||||||
_data.display();
|
_data.display();
|
||||||
if (_data.getType() == enet::HTTPReqType::GET) {
|
if (_data.getType() == enet::HTTPReqType::HTTP_GET) {
|
||||||
if (_data.getUri() == "plop.txt") {
|
if (_data.getUri() == "plop.txt") {
|
||||||
enet::HttpAnswer answer(enet::HTTPAnswerCode::c200_ok);
|
enet::HttpAnswer answer(enet::HTTPAnswerCode::c200_ok);
|
||||||
std::string data = "<html><head></head></body>coucou</body></html>";
|
std::string data = "<html><head></head></body>coucou</body></html>";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user