did not track for a while since I forgot about git repo. Version 0.1 of the library, during tests
parent
7fc95f2307
commit
ab218dae4e
|
@ -1,9 +1,9 @@
|
|||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include "ClientSocket.h"
|
||||
using namespace NetSocket;
|
||||
using namespace NetSocketPP;
|
||||
|
||||
ClientSocket::ClientSocket(std::string host = NULL, std::string service, std::string protocol): NetSocket(host, service, protocol) {
|
||||
ClientSocket::ClientSocket(std::string host, std::string service, std::string protocol): NetSocket(host, service, protocol) {
|
||||
if(protocol == "TCP") {
|
||||
int conret;
|
||||
conret = connect(_descriptor, _servinfo->ai_addr, _servinfo->ai_addrlen);
|
||||
|
@ -14,32 +14,33 @@ throw NetworkException("connect", strerror(errno));
|
|||
}
|
||||
|
||||
int ClientSocket::send(std::string msg, int flags=0) {
|
||||
if(protocol == "TCP") {
|
||||
int sr = send(_descriptor, msg.c_str(), msg.length(), flags);
|
||||
if(_protocol == "TCP") {
|
||||
int sr = ::send(_descriptor, msg.c_str(), msg.length(), flags);
|
||||
if(sr == -1) {
|
||||
throw NetworkException("send", strerror(errno));
|
||||
}
|
||||
return sr;
|
||||
} else if(protocol == "UDP") {
|
||||
int sr = sendto(_descriptor, msg.c_str(), msg.length(), flags, _servinfo->ai_addr, _servinfo->ai_addrlen);
|
||||
} else if(_protocol == "UDP") {
|
||||
int sr = ::sendto(_descriptor, msg.c_str(), msg.length(), flags, _servinfo->ai_addr, _servinfo->ai_addrlen);
|
||||
if(sr == -1) {
|
||||
throw NetworkException("sendto", strerror(errno));
|
||||
}
|
||||
return sr;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ClientSocket::recv(int flags) {
|
||||
if(protocol == "TCP") {
|
||||
int rr = recv(_descriptor, _buf, 99999, flags);
|
||||
if(_protocol == "TCP") {
|
||||
int rr = ::recv(_descriptor, buf, 99999, flags);
|
||||
if(rr == -1) {
|
||||
throw NetworkException("recv", strerror(errno));
|
||||
} else if(rr == 0) {
|
||||
throw NetworkException("recv", "Remote end has closed the connection.");
|
||||
}
|
||||
return rr;
|
||||
} else if(protocol == "UDP") {
|
||||
int rr = recvfrom(_descriptor, _buf, 99999, flags, _servinfo->ai_addr, _servinfo->ai_addrlen);
|
||||
} else if(_protocol == "UDP") {
|
||||
int rr = ::recvfrom(_descriptor, buf, 99999, flags, (sockaddr*)&_their_addr, &_addr_size);
|
||||
if(rr == -1) {
|
||||
throw NetworkException("recvfrom", strerror(errno));
|
||||
} else if(rr == 0) {
|
||||
|
@ -48,8 +49,9 @@ int ClientSocket::recv(int flags) {
|
|||
buf[rr] = '\0';
|
||||
return rr;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::string ClientSocket::get() {
|
||||
return static_cast<std::string>(_buf);
|
||||
return static_cast<std::string>(buf);
|
||||
}
|
||||
|
|
|
@ -1,30 +1,31 @@
|
|||
#ifndef _CLIENTSOCKET_H
|
||||
#define _CLIENTSOCKET_H
|
||||
#include "NetSocket.h"
|
||||
#include "NetworkException.h"
|
||||
/// \file ClientSocket.h
|
||||
/// \brief An implementation of a client socket.
|
||||
/// \author Phitherek_
|
||||
/// \date 2012
|
||||
/// \version 0.1
|
||||
|
||||
/// \namespace NetSocket
|
||||
/// \namespace NetSocketPP
|
||||
/// \brief A namespace for all library names
|
||||
namespace NetSocket {
|
||||
namespace NetSocketPP {
|
||||
/// \class ClientSocket
|
||||
/// \brief An implementation of a client socket. Inherits from NetSocket.
|
||||
class ClientSocket: public NetSocket {
|
||||
protected:
|
||||
const char buf[100000]; ///< A large buffer for data.
|
||||
char buf[100000]; ///< A large buffer for data.
|
||||
public:
|
||||
ClientSocket(std::string host = NULL, std::string service, std::string protocol); ///< \brief A constructor with parameters, that creates and connects the socket.
|
||||
ClientSocket(std::string host, std::string service, std::string protocol); ///< \brief A constructor with parameters, that creates and connects the socket.
|
||||
///< \param host A hostname or IP address of socket destination.
|
||||
///< \param port A port or service identifier, where socket is to be opened.
|
||||
///< \param protocol A protocol of the socket, TCP or UDP.
|
||||
int send(std::string msg, int flags=0); ///< \brief A function, that sends data through the socket.
|
||||
int send(std::string msg, int flags); ///< \brief A function, that sends data through the socket.
|
||||
///< \param msg A message to send.
|
||||
///< \param flags Socket flags, default 0.
|
||||
///< \return Number of bytes sent.
|
||||
int recv(int flags=0); ///< \brief A function, that receives data through the socket.
|
||||
int recv(int flags); ///< \brief A function, that receives data through the socket.
|
||||
///< \param flags Socket flags, default 0.
|
||||
///< \return Number of bytes received.
|
||||
std::string get(); ///< \brief A function returning recently recv-d data.
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,208 @@
|
|||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <cctype>
|
||||
#include "HTTPClientSocket.h"
|
||||
using namespace NetSocketPP;
|
||||
|
||||
HTTPReply::HTTPReply() {
|
||||
_raw = "";
|
||||
_protocol = "";
|
||||
_response = "";
|
||||
_timestamp = "";
|
||||
_server = "";
|
||||
_cl = 0;
|
||||
_connection = "";
|
||||
_ct = "";
|
||||
_content = "";
|
||||
}
|
||||
|
||||
HTTPReply::HTTPReply(std::string raw) {
|
||||
_raw = raw;
|
||||
_protocol = "";
|
||||
_response = "";
|
||||
_timestamp = "";
|
||||
_server = "";
|
||||
_cl = 0;
|
||||
_connection = "";
|
||||
_ct = "";
|
||||
_content = "";
|
||||
}
|
||||
|
||||
HTTPReply::~HTTPReply() {
|
||||
_raw = "";
|
||||
_protocol = "";
|
||||
_response = "";
|
||||
_timestamp = "";
|
||||
_server = "";
|
||||
_cl = 0;
|
||||
_connection = "";
|
||||
_ct = "";
|
||||
_content = "";
|
||||
}
|
||||
|
||||
void HTTPReply::parse() {
|
||||
std::string action = "firstline";
|
||||
std::string parsed = "";
|
||||
bool postspace = false;
|
||||
for(unsigned int i = 0; i < _raw.length(); i++) {
|
||||
if(action == "firstline") {
|
||||
if(_raw[i] == ' ') {
|
||||
_protocol = parsed;
|
||||
parsed = "";
|
||||
postspace = true;
|
||||
} else if(postspace == true) {
|
||||
if(_raw[i] == '\n') {
|
||||
_response = parsed;
|
||||
parsed = "";
|
||||
action = "reqparse";
|
||||
} else {
|
||||
parsed += _raw[i];
|
||||
}
|
||||
} else {
|
||||
parsed += _raw[i];
|
||||
}
|
||||
} else if(action == "reqparse") {
|
||||
if(_raw[i] == ':') {
|
||||
i++;
|
||||
if(parsed == "Date" || parsed == "Request timestamp") {
|
||||
action = "timestamp";
|
||||
} else if(parsed == "Server" || parsed == "server") {
|
||||
action = "server";
|
||||
} else if(parsed == "Content-Length") {
|
||||
action = "cl";
|
||||
} else if(parsed == "Connection") {
|
||||
action = "conn";
|
||||
} else if(parsed == "Content-Type") {
|
||||
action = "ct";
|
||||
}
|
||||
parsed = "";
|
||||
} else if(_raw[i] == '\n') {
|
||||
if(_raw[i+1] == '\n') {
|
||||
action = "content";
|
||||
}
|
||||
parsed = "";
|
||||
} else {
|
||||
parsed += _raw[i];
|
||||
}
|
||||
} else if(action == "timestamp") {
|
||||
if(_raw[i] == '\n') {
|
||||
action = "reqparse";
|
||||
} else {
|
||||
_timestamp += _raw[i];
|
||||
}
|
||||
} else if(action == "server") {
|
||||
if(_raw[i] == '\n') {
|
||||
action = "reqparse";
|
||||
} else {
|
||||
_server += _raw[i];
|
||||
}
|
||||
} else if(action == "cl") {
|
||||
std::string scl = "";
|
||||
if(_raw[i] == '\n') {
|
||||
for(unsigned int j = 0; j < scl.length(); j++) {
|
||||
if(!isdigit(scl[j])) {
|
||||
throw SocketException("Content-Length is not a number!");
|
||||
}
|
||||
}
|
||||
_cl = atoi(scl.c_str());
|
||||
scl = "";
|
||||
action = "reqparse";
|
||||
} else {
|
||||
scl += _raw[i];
|
||||
}
|
||||
} else if(action == "connection") {
|
||||
if(_raw[i] == '\n') {
|
||||
action = "reqparse";
|
||||
} else {
|
||||
_connection += _raw[i];
|
||||
}
|
||||
} else if(action == "ct") {
|
||||
if(_raw[i] == '\n') {
|
||||
action = "reqparse";
|
||||
} else {
|
||||
_ct += _raw[i];
|
||||
}
|
||||
} else if(action == "content") {
|
||||
_content += _raw[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HTTPReply::addToContent(std::string cp) {
|
||||
for(unsigned int i = 0; i < cp.length(); i++) {
|
||||
_content += cp[i];
|
||||
}
|
||||
}
|
||||
|
||||
std::string HTTPReply::getProtocol() {
|
||||
return _protocol;
|
||||
}
|
||||
|
||||
std::string HTTPReply::getResponse() {
|
||||
return _response;
|
||||
}
|
||||
|
||||
std::string HTTPReply::getTimestamp() {
|
||||
return _timestamp;
|
||||
}
|
||||
|
||||
std::string HTTPReply::getServer() {
|
||||
return _server;
|
||||
}
|
||||
|
||||
unsigned int HTTPReply::getContentLength() {
|
||||
return _cl;
|
||||
}
|
||||
|
||||
std::string HTTPReply::getConnection() {
|
||||
return _connection;
|
||||
}
|
||||
|
||||
std::string HTTPReply::getContentType() {
|
||||
return _ct;
|
||||
}
|
||||
|
||||
std::string HTTPReply::getContent() {
|
||||
return _content;
|
||||
}
|
||||
|
||||
std::string HTTPReply::getRaw() {
|
||||
return _raw;
|
||||
}
|
||||
|
||||
HTTPClientSocket::HTTPClientSocket(std::string host = NULL, std::string service = "http", std::string docRequest = "/"): ClientSocket(host, service, "TCP") {
|
||||
_request = "";
|
||||
_request += "GET ";
|
||||
_request += docRequest;
|
||||
_request += " HTTP/1.0\n";
|
||||
if(host != "") {
|
||||
_request += "Host: ";
|
||||
_request += host;
|
||||
}
|
||||
_request += "\n";
|
||||
send(_request, 0);
|
||||
recv(0);
|
||||
std::string rawreply;
|
||||
rawreply = CStrToString(buf);
|
||||
HTTPReply reply(rawreply);
|
||||
_reply = reply;
|
||||
_reply.parse();
|
||||
std::string rawcontent = _reply.getContent();
|
||||
unsigned int cl = _reply.getContentLength();
|
||||
while(rawcontent.length() < cl) {
|
||||
for(int i = 0; i < 100000; i++) {
|
||||
buf[i] = 0;
|
||||
}
|
||||
recv(0);
|
||||
_reply.addToContent(CStrToString(buf));
|
||||
rawcontent = _reply.getContent();
|
||||
}
|
||||
}
|
||||
|
||||
HTTPReply HTTPClientSocket::getReply() {
|
||||
return _reply;
|
||||
}
|
||||
|
||||
std::string HTTPClientSocket::getRequest() {
|
||||
return _request;
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
#ifndef _HTTPCLIENTSOCKET_H
|
||||
#define _HTTPCLIENTSOCKET_H
|
||||
#include "ClientSocket.h"
|
||||
#include "SocketException.h"
|
||||
/// \file HTTPClientSocket.h
|
||||
/// \brief An implementation of HTTP Client Socket.
|
||||
/// \author Phitherek_
|
||||
/// \date 2012
|
||||
/// \version 0.1
|
||||
/// \namespace NetSocketPP
|
||||
/// \brief A namespace for all library names
|
||||
namespace NetSocketPP {
|
||||
/// \class HTTPReply
|
||||
/// \brief A class representing HTTP Reply.
|
||||
class HTTPReply {
|
||||
private:
|
||||
std::string _raw;
|
||||
std::string _protocol;
|
||||
std::string _response;
|
||||
std::string _timestamp;
|
||||
std::string _server;
|
||||
unsigned int _cl;
|
||||
std::string _connection;
|
||||
std::string _ct;
|
||||
std::string _content;
|
||||
public:
|
||||
HTTPReply(); ///< A constructor.
|
||||
HTTPReply(std::string raw); ///< \brief A constructor with parameter
|
||||
///< \param raw Raw reply from recv.
|
||||
~HTTPReply(); ///< A destructor.
|
||||
void parse(); ///< HTTP reply parser
|
||||
void addToContent(std::string cp); ///< \brief A function, that adds more parts of the content to the reply if necessary
|
||||
///< \param cp Part of the content to be added.
|
||||
std::string getRaw(); ///< \brief A function returning raw HTTP reply.
|
||||
///< \return Raw HTTP reply.
|
||||
std::string getProtocol(); ///< \brief A function returning HTTP protocol information.
|
||||
///< \return HTTP protocol information.
|
||||
std::string getResponse(); ///< \brief A function returning HTTP response message.
|
||||
///< \return HTTP response message.
|
||||
std::string getTimestamp(); ///< \brief A function returning timestamp.
|
||||
///< \return Timestamp.
|
||||
std::string getServer(); ///< \brief A function returning server information.
|
||||
///< \return Server information.
|
||||
unsigned int getContentLength(); ///< \brief A function returning length of content.
|
||||
///< \return Length of content.
|
||||
std::string getConnection(); ///< \brief A function returning connection status.
|
||||
///< \return Connection status.
|
||||
std::string getContentType(); ///< \brief A function returning type of content.
|
||||
///< \return Type of content.
|
||||
std::string getContent(); ///< \brief A function returning received content.
|
||||
///< \return Received content.
|
||||
};
|
||||
/// \class HTTPClientSocket
|
||||
/// \brief A class representing HTTP client socket.
|
||||
class HTTPClientSocket: public ClientSocket {
|
||||
private:
|
||||
HTTPReply _reply;
|
||||
std::string _request;
|
||||
public:
|
||||
HTTPClientSocket(std::string host, std::string service, std::string docRequest); ///< \brief A constructor with parameters.
|
||||
///< \param host Hostname or IP of socket destination, defaults to NULL.
|
||||
///< \param service Service port or identifier, defaults to HTTP.
|
||||
///< \param docRequest A document to request from the server, defaults to root/index (/).
|
||||
HTTPReply getReply(); ///< \brief A function returning a HTTPReply.
|
||||
///< \return HTTPReply object containing received data.
|
||||
std::string getRequest(); ///< \brief A function returning the request used in the socket.
|
||||
///< \return The HTTP request used to obtain data.
|
||||
};
|
||||
}
|
||||
#endif
|
Binary file not shown.
|
@ -0,0 +1,17 @@
|
|||
CXXFLAGS=-Wall -fPIC
|
||||
CXXFLAGS2=-shared
|
||||
TESTCXXFLAGS=-Wall
|
||||
all:
|
||||
${CXX} ${CXXFLAGS} -c *.cpp
|
||||
${CXX} ${CXXFLAGS2} -Wl,-soname,libnetsocketpp.so.0 -o libnetsocketpp.so.0.1 *.o
|
||||
install:
|
||||
cp libnetsocketpp.so.0.1 /usr/lib
|
||||
mkdir /usr/include/NetSocket++
|
||||
cp *.h /usr/include/NetSocket++
|
||||
ln -sf /usr/lib/libnetsocketpp.so.0.1 /usr/lib/libnetsocketpp.so.0
|
||||
ln -sf /usr/lib/libnetsocketpp.so.0.1 /usr/lib/libnetsocketpp.so
|
||||
test:
|
||||
${CXX} ${TESTCXXFLAGS} -o tests/nstest tests/nstest.cpp NetSocket.cpp ClientSocket.cpp HTTPClientSocket.cpp ServerSocket.cpp NetworkException.cpp SocketException.cpp
|
||||
debugtest:
|
||||
${CXX} ${TESTCXXFLAGS} -g -o tests/nstest tests/nstest.cpp NetSocket.cpp ClientSocket.cpp HTTPClientSocket.cpp ServerSocket.cpp NetworkException.cpp SocketException.cpp
|
||||
|
|
@ -3,12 +3,13 @@
|
|||
#include "NetSocket.h"
|
||||
#include "NetworkException.h"
|
||||
#include "SocketException.h"
|
||||
using namespace NetSocket;
|
||||
using namespace NetSocketPP;
|
||||
|
||||
NetSocket::NetSocket(std::string host = NULL, std::string service, std::string protocol) {
|
||||
NetSocket::NetSocket(std::string host, std::string service, std::string protocol) {
|
||||
_yes=1;
|
||||
memset(&_hints, 0, sizeof(_hints));
|
||||
_hints.ai_family = AF_UNSPEC;
|
||||
_addr_size = sizeof(_their_addr);
|
||||
if(protocol == "TCP") {
|
||||
_hints.ai_socktype = SOCK_STREAM;
|
||||
} else if(protocol == "UDP") {
|
||||
|
@ -36,12 +37,8 @@ throw NetworkException("socket", strerror(errno));
|
|||
}
|
||||
inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr), _caddr, sizeof(_caddr));
|
||||
_servinfo = p;
|
||||
if(protocol = "TCP") {
|
||||
if(protocol == "TCP") {
|
||||
setsockopt(_descriptor, SOL_SOCKET, SO_REUSEADDR, &_yes, sizeof(int));
|
||||
int bindret = bind(_descriptor, _servinfo->ai_addr, _servinfo->ai_addrlen);
|
||||
if(bindret == -1) {
|
||||
throw NetworkException("bind", strerror(errno));
|
||||
}
|
||||
}
|
||||
_protocol = protocol;
|
||||
_host = host;
|
||||
|
|
28
NetSocket.h
28
NetSocket.h
|
@ -1,5 +1,5 @@
|
|||
#ifndef NETSOCKET_H
|
||||
#define NETSOCKET_H
|
||||
#ifndef _NETSOCKET_H
|
||||
#define _NETSOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <arpa/inet.h>
|
||||
|
@ -8,32 +8,46 @@
|
|||
#include <sys/wait.h>
|
||||
#include <signal.h>
|
||||
#include <string>
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
/// \file NetSocket.h
|
||||
/// \brief A library designed to simplify the use of UNIX Network Sockets in the means of OOP.
|
||||
/// \author Phitherek_
|
||||
/// \date 2012
|
||||
/// \version 0.1
|
||||
|
||||
/// \namespace NetSocket
|
||||
/// \namespace NetSocketPP
|
||||
/// \brief A namespace for all library names.
|
||||
namespace NetSocket {
|
||||
|
||||
namespace NetSocketPP {
|
||||
/// \fn CStrToString
|
||||
/// \brief A function, that converts table of chars (a C-style string) into std::string
|
||||
/// \param cstr A C-style string to be converted.
|
||||
/// \return A std::string with the content of the input.
|
||||
inline std::string CStrToString(char* cstr) {
|
||||
std::string str = "";
|
||||
for(int i = 0; cstr[i] != '\000'; i++) {
|
||||
str += cstr[i];
|
||||
}
|
||||
return str;
|
||||
}
|
||||
/// \class NetSocket
|
||||
/// \brief A class, that represents network connection - socket.
|
||||
class NetSocket {
|
||||
protected:
|
||||
int _descriptor; ///< Socket descriptor.
|
||||
const int _yes; ///< Needed for implementation purposes.
|
||||
int _yes; ///< Needed for implementation purposes.
|
||||
int _status; ///< Needed for implementation purposes.
|
||||
char _caddr[INET6_ADDRSTRLEN]; ///< A structure that stores IP address.
|
||||
addrinfo _hints; ///< Needed for implementation purposes.
|
||||
addrinfo *_servinfo; ///< Needed for implementation purposes.
|
||||
sockaddr_storage _their_addr; ///< Needed for implementation purposes.
|
||||
socklen_t _addr_size; ///< Needed for implementation purposes.
|
||||
std::string _host; ///< A host to which a socket is connecting to/on which a server socket is opened.
|
||||
std::string _service; ///< A port or a string identyfing service that socket is connecting to/which server is being opened.
|
||||
std::string _protocol; ///< A protocol of the socket: TCP/UDP.
|
||||
void *get_in_addr(sockaddr* sa); ///< Needed for implementation purposes.
|
||||
public:
|
||||
NetSocket(std::string host = NULL, std::string service, std::string protocol); ///< \brief A constructor with parameters, that creates a socket.
|
||||
NetSocket(std::string host, std::string service, std::string protocol); ///< \brief A constructor with parameters, that creates a socket.
|
||||
///< \param host A hostname or IP address of socket destination.
|
||||
///< \param port A port or service identifier, where socket is to be opened.
|
||||
///< \param protocol A protocol of the socket, TCP or UDP.
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,14 @@
|
|||
#ifndef _NETSOCKETPP_H
|
||||
#define _NETSOCKETPP_H
|
||||
/// \file NetSocketPP.h
|
||||
/// \brief A common header for NetSocket++ library.
|
||||
/// \author Phitherek_
|
||||
/// \date 2013
|
||||
/// \version 0.1
|
||||
#include "NetSocket.h"
|
||||
#include "SocketException.h"
|
||||
#include "NetworkException.h"
|
||||
#include "ClientSocket.h"
|
||||
#include "ServerSocket.h"
|
||||
#include "HTTPClientSocket.h"
|
||||
#endif
|
|
@ -1,7 +1,7 @@
|
|||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include "NetworkException.h"
|
||||
using namespace NetSocket;
|
||||
using namespace NetSocketPP;
|
||||
|
||||
NetworkException::NetworkException(std::string cmd, std::string msg) {
|
||||
_cmd = cmd;
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
/// \version 0.1
|
||||
#include <exception>
|
||||
#include <string>
|
||||
/// \namespace NetSocket
|
||||
/// \namespace NetSocketPP
|
||||
/// \brief A namespace for all library names
|
||||
namespace NetSocket {
|
||||
namespace NetSocketPP {
|
||||
/// \class NetworkException
|
||||
/// \brief A class representing an exception with network.
|
||||
class NetworkException: public std::exception {
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,148 @@
|
|||
#include "ServerSocket.h"
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
using namespace NetSocketPP;
|
||||
|
||||
ServerLoopCondition::ServerLoopCondition(bool state) {
|
||||
_cond = state;
|
||||
}
|
||||
|
||||
void ServerLoopCondition::setState(bool state) {
|
||||
_cond = state;
|
||||
}
|
||||
|
||||
bool ServerLoopCondition::operator()() {
|
||||
return _cond;
|
||||
}
|
||||
|
||||
ServerFunctionArgs::ServerFunctionArgs() {
|
||||
_tab = NULL;
|
||||
_size = 0;
|
||||
}
|
||||
|
||||
ServerFunctionArgs::ServerFunctionArgs(ServerFunctionArgs& sfa) {
|
||||
if(sfa._tab == NULL) {
|
||||
_tab = NULL;
|
||||
_size = 0;
|
||||
} else {
|
||||
_size = sfa._size;
|
||||
_tab = new std::string[_size];
|
||||
for(int i = 0; i < _size; i++) {
|
||||
_tab[i] = sfa._tab[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ServerFunctionArgs::~ServerFunctionArgs() {
|
||||
_size = 0;
|
||||
if(_tab != NULL) {
|
||||
delete[] _tab;
|
||||
}
|
||||
_tab = NULL;
|
||||
}
|
||||
|
||||
void ServerFunctionArgs::addArgument(std::string arg) {
|
||||
int newSize = _size+1;
|
||||
std::string* newTab = NULL;
|
||||
newTab = new std::string[newSize];
|
||||
for(int i = 0; i < _size; i++) {
|
||||
newTab[i] = _tab[i];
|
||||
}
|
||||
newTab[newSize-1] = arg;
|
||||
_size = newSize;
|
||||
delete[] _tab;
|
||||
_tab = newTab;
|
||||
}
|
||||
|
||||
std::string ServerFunctionArgs::getArgument(int idx) {
|
||||
if(idx < 0 or idx >= _size) {
|
||||
throw SocketException("Index out of bounds!");
|
||||
} else {
|
||||
return _tab[idx];
|
||||
}
|
||||
}
|
||||
|
||||
std::string ServerFunctionArgs::operator[](int idx) {
|
||||
return getArgument(idx);
|
||||
}
|
||||
|
||||
ServerSocket::ServerSocket(std::string host, std::string service, std::string protocol): NetSocket(host, service, protocol) {
|
||||
if(protocol == "TCP") {
|
||||
int bindret = bind(_descriptor, _servinfo->ai_addr, _servinfo->ai_addrlen);
|
||||
if(bindret == 1) {
|
||||
throw NetworkException("bind", strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
ServerSocket::~ServerSocket() {
|
||||
close(_newDescriptor);
|
||||
}
|
||||
|
||||
void ServerSocket::startServer(ServerFunctionArgs functionOutput ,ServerFunctionArgs (*serverMain)(ServerFunctionArgs, ServerLoopCondition&, ServerSocket*), ServerFunctionArgs functionInput, ServerLoopCondition condition, int connectionLimit) {
|
||||
if(_protocol == "UDP") {
|
||||
throw SocketException("startServer() works only with TCP! Use send() and recv() methods to transfer data via UDP!");
|
||||
}
|
||||
int lr = listen(_descriptor, connectionLimit);
|
||||
if(lr == -1) {
|
||||
throw NetworkException("listen", strerror(errno));
|
||||
}
|
||||
_sa.sa_handler = sigchld_handler;
|
||||
sigemptyset(&_sa.sa_mask);
|
||||
_sa.sa_flags = SA_RESTART;
|
||||
if(sigaction(SIGCHLD, &_sa, NULL) == -1) {
|
||||
throw SocketException("Sigaction failed!");
|
||||
}
|
||||
while(condition()) {
|
||||
_newDescriptor = accept(_descriptor, (sockaddr*)&_their_addr, &_addr_size);
|
||||
if(_newDescriptor == -1) {
|
||||
throw NetworkException("accept", strerror(errno));
|
||||
}
|
||||
if(!fork()) {
|
||||
close(_descriptor);
|
||||
functionOutput = serverMain(functionInput, condition, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ServerSocket::send(std::string msg, int flags) {
|
||||
if(_protocol == "TCP") {
|
||||
int sr = ::send(_descriptor, msg.c_str(), msg.length(), flags);
|
||||
if(sr == -1) {
|
||||
throw NetworkException("send", strerror(errno));
|
||||
}
|
||||
return sr;
|
||||
} else if(_protocol == "UDP") {
|
||||
int sr = ::sendto(_descriptor, msg.c_str(), msg.length(), flags, _servinfo->ai_addr, _servinfo->ai_addrlen);
|
||||
if(sr == -1) {
|
||||
throw NetworkException("sendto", strerror(errno));
|
||||
}
|
||||
return sr;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ServerSocket::recv(int flags) {
|
||||
if(_protocol == "TCP") {
|
||||
int rr = ::recv(_descriptor, _buf, 99999, flags);
|
||||
if(rr == -1) {
|
||||
throw NetworkException("recv", strerror(errno));
|
||||
} else if(rr == 0) {
|
||||
throw NetworkException("recv", "Remote end has closed the connection.");
|
||||
}
|
||||
return rr;
|
||||
} else if(_protocol == "UDP") {
|
||||
int rr = ::recvfrom(_descriptor, _buf, 99999, flags, (sockaddr*)&_their_addr, &_addr_size);
|
||||
if(rr == -1) {
|
||||
throw NetworkException("recvfrom", strerror(errno));
|
||||
} else if(rr == 0) {
|
||||
throw NetworkException("recvfrom", "Remote end has closed the connection.");
|
||||
}
|
||||
_buf[rr] = '\0';
|
||||
return rr;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::string ServerSocket::get() {
|
||||
return static_cast<std::string>(_buf);
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
#ifndef _SERVERSOCKET_H
|
||||
#define _SERVERSOCKET_H
|
||||
#include "NetSocket.h"
|
||||
#include "NetworkException.h"
|
||||
#include "SocketException.h"
|
||||
/// \file ServerSocket.h
|
||||
/// \brief An implementation of a server socket.
|
||||
/// \author Phitherek_
|
||||
/// \date 2013
|
||||
/// \version 0.1
|
||||
|
||||
/// \fn sigchld_handler
|
||||
/// \brief Signal handler, needed for implementation purposes
|
||||
/// \param s Needed for implementation purposes
|
||||
inline void sigchld_handler(int s) {
|
||||
while(waitpid(-1, NULL, WNOHANG) > 0);
|
||||
}
|
||||
|
||||
/// \namespace NetSocketPP
|
||||
/// \brief A namespace for all library names
|
||||
namespace NetSocketPP {
|
||||
/// \class LoopCondition
|
||||
/// \brief A class controlling main server loop.
|
||||
class ServerLoopCondition {
|
||||
private:
|
||||
bool _cond;
|
||||
public:
|
||||
ServerLoopCondition(bool state); ///< \brief A constructor with parameter.
|
||||
///< \param state Initial state of the condition.
|
||||
bool operator()(); ///< \brief An operator() returning boolean value controlling the loop.
|
||||
///< \return Boolean for controlling the loop.
|
||||
void setState(bool state); ///< \brief A function, that sets the condition state.
|
||||
///< \param state A condition state.
|
||||
};
|
||||
/// \class ServerFunctionArgs
|
||||
/// \brief A class for storing server function arguments.
|
||||
class ServerFunctionArgs {
|
||||
private:
|
||||
std::string* _tab;
|
||||
int _size;
|
||||
public:
|
||||
ServerFunctionArgs(); ///< A constructor.
|
||||
ServerFunctionArgs(ServerFunctionArgs& sfa); ///< \brief A copy constructor.
|
||||
///< \param sfa An object to be copied.
|
||||
~ServerFunctionArgs(); ///< A destructor.
|
||||
void addArgument(std::string arg); ///< \brief Function adding an argument to the list.
|
||||
///< \param arg An argument to be added, of type std::string.
|
||||
std::string getArgument(int idx); ///< \brief Function returning the argument of given index number.
|
||||
///< \param idx Index of the argument.
|
||||
///< \return The argument.
|
||||
std::string operator[](int idx); ///< \brief Operator[] returning the argument of given index number.
|
||||
///< \param idx Index of the argument.
|
||||
///< \return The argument.
|
||||
};
|
||||
/// \class ServerSocket
|
||||
/// \brief An implementation of the server socket.
|
||||
class ServerSocket: public NetSocket {
|
||||
private:
|
||||
int _newDescriptor;
|
||||
char _buf[100000];
|
||||
struct sigaction _sa;
|
||||
public:
|
||||
ServerSocket(std::string host, std::string service, std::string protocol); ///< \brief A constructor with parameters.
|
||||
///< \param host A hostname or IP adress of socket destination, defaults to NULL.
|
||||
///< \param service Port or service that socket should be connected with.
|
||||
///< \param protocol Socket protocol, TCP or UDP.
|
||||
~ServerSocket(); ///< A destructor.
|
||||
void startServer(ServerFunctionArgs functionOutput ,ServerFunctionArgs (*serverMain)(ServerFunctionArgs, ServerLoopCondition&, ServerSocket*), ServerFunctionArgs functionInput, ServerLoopCondition condition, int connectionLimit); ///< \brief A function that starts TCP server.
|
||||
///< \param functionOutput A ServerFunctionArgs object that will store server function result.
|
||||
///< \param serverMain An user-defined function, that returns ServerFunctionArgs object - results of the server function with arguments: ServerFunctionArgs object - arguments to the server function, reference to ServerLoopCondition object - an object controlling the main server loop, pointer to ServerSocket object - for passing socket information in that order.
|
||||
///< \param functionInput A ServerFunctionArgs object with server function arguments.
|
||||
///< \param condition A ServerLoopCondition object set to proper value.
|
||||
///< \param connectionLimit Maximum number of accepted connections.
|
||||
int send(std::string msg, int flags=0); ///< \brief A function that sends data through the socket.
|
||||
///< \param msg A message/data to send, of type std::string.
|
||||
///< \param flags Send flags, defaulting to 0.
|
||||
///< \return Number of bytes sent.
|
||||
int recv(int flags = 0); ///< \brief A function that receives data through the socket.
|
||||
///< \param flags Receive flags, defaulting to 0.
|
||||
///< \return Number of bytes received.
|
||||
std::string get(); ///< \brief A function returning received data.
|
||||
///< \return Received data as string.
|
||||
};
|
||||
}
|
||||
#endif
|
Binary file not shown.
|
@ -1,7 +1,7 @@
|
|||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include "SocketException.h"
|
||||
using namespace NetSocket;
|
||||
using namespace NetSocketPP;
|
||||
|
||||
SocketException::SocketException(std::string msg) {
|
||||
_msg = msg;
|
||||
|
@ -13,7 +13,7 @@ _msg = "";
|
|||
|
||||
const char* SocketException::what() const throw() {
|
||||
std::string str = "";
|
||||
str += "Failure occured in NetSocket++: ";
|
||||
str += "Error occured in NetSocket++: ";
|
||||
str += _msg;
|
||||
return str.c_str();
|
||||
}
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
/// \version 0.1
|
||||
#include <exception>
|
||||
#include <string>
|
||||
/// \namespace NetSocket
|
||||
/// \namespace NetSocketPP
|
||||
/// \brief A namespace for all library names
|
||||
namespace NetSocket {
|
||||
namespace NetSocketPP {
|
||||
/// \class SocketException
|
||||
/// \brief A class representing an exception with socket classes
|
||||
class SocketException: public std::exception {
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,10 @@
|
|||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include "../NetSocketPP.h"
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
NetSocketPP::NetSocket ns("phitherek.mooo.com", "http", "TCP");
|
||||
cout << "Host IP: " << ns.getIP() << endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
Loading…
Reference in New Issue