[DEV] first implementation of windows socket (missing read)

This commit is contained in:
Edouard DUPIN 2016-10-06 01:28:56 +02:00
parent 5cb8ea40e3
commit a979e33401
11 changed files with 428 additions and 169 deletions

View File

@ -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";
} }

View File

@ -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) {

View File

@ -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) {

View File

@ -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;

View File

@ -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

View File

@ -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;
} }

View File

@ -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
View 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();
}

View File

@ -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();
} }

View File

@ -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

View File

@ -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>";