diff --git a/ClientSocket.cpp b/ClientSocket.cpp index 6df2684..d83ad74 100644 --- a/ClientSocket.cpp +++ b/ClientSocket.cpp @@ -10,6 +10,11 @@ conret = connect(_descriptor, _servinfo->ai_addr, _servinfo->ai_addrlen); if(conret == -1) { throw NetworkException("connect", strerror(errno)); } +} else if(protocol == "UDP") { +int bindret = bind(_descriptor, _servinfo->ai_addr, _servinfo->ai_addrlen); + if(bindret == 1) { + throw NetworkException("bind", strerror(errno)); + } } } diff --git a/ClientSocket.o b/ClientSocket.o deleted file mode 100644 index 08ca8b7..0000000 Binary files a/ClientSocket.o and /dev/null differ diff --git a/HTTPClientSocket.cpp b/HTTPClientSocket.cpp index a979d2e..89c143b 100644 --- a/HTTPClientSocket.cpp +++ b/HTTPClientSocket.cpp @@ -43,21 +43,23 @@ _content = ""; void HTTPReply::parse() { std::string action = "firstline"; std::string parsed = ""; + std::string scl = ""; 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') { + if(postspace == true) { + if(_raw[i] == '\r') { _response = parsed; parsed = ""; - action = "reqparse"; + action = "reqparse"; + i++; } else { - parsed += _raw[i]; + parsed += _raw[i]; } + } else if(_raw[i] == ' ') { + _protocol = parsed; + parsed = ""; + postspace = true; } else { parsed += _raw[i]; } @@ -76,29 +78,32 @@ void HTTPReply::parse() { action = "ct"; } parsed = ""; - } else if(_raw[i] == '\n') { - if(_raw[i+1] == '\n') { + } else if(_raw[i] == '\r') { + if(_raw[i-2] == '\r') { action = "content"; } + i++; parsed = ""; } else { parsed += _raw[i]; } } else if(action == "timestamp") { - if(_raw[i] == '\n') { + if(_raw[i] == '\r') { + i++; action = "reqparse"; } else { _timestamp += _raw[i]; } } else if(action == "server") { - if(_raw[i] == '\n') { + if(_raw[i] == '\r') { + i++; action = "reqparse"; } else { _server += _raw[i]; } } else if(action == "cl") { - std::string scl = ""; - if(_raw[i] == '\n') { + if(_raw[i] == '\r') { + i++; for(unsigned int j = 0; j < scl.length(); j++) { if(!isdigit(scl[j])) { throw SocketException("Content-Length is not a number!"); @@ -110,14 +115,16 @@ void HTTPReply::parse() { } else { scl += _raw[i]; } -} else if(action == "connection") { - if(_raw[i] == '\n') { +} else if(action == "conn") { + if(_raw[i] == '\r') { + i++; action = "reqparse"; } else { _connection += _raw[i]; } } else if(action == "ct") { - if(_raw[i] == '\n') { + if(_raw[i] == '\r') { + i++; action = "reqparse"; } else { _ct += _raw[i]; @@ -179,7 +186,7 @@ HTTPClientSocket::HTTPClientSocket(std::string host = NULL, std::string service _request += "Host: "; _request += host; } - _request += "\n"; + _request += "\n\n"; send(_request, 0); recv(0); std::string rawreply; diff --git a/HTTPClientSocket.o b/HTTPClientSocket.o deleted file mode 100644 index 6dc55cd..0000000 Binary files a/HTTPClientSocket.o and /dev/null differ diff --git a/Makefile b/Makefile index 62b5a29..f821e7e 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ CXXFLAGS=-Wall -fPIC CXXFLAGS2=-shared -TESTCXXFLAGS=-Wall +TESTCXXFLAGS=-Wall -lnetsocketpp all: ${CXX} ${CXXFLAGS} -c *.cpp ${CXX} ${CXXFLAGS2} -Wl,-soname,libnetsocketpp.so.0 -o libnetsocketpp.so.0.1 *.o @@ -11,7 +11,19 @@ install: 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 + ${CXX} ${TESTCXXFLAGS} -o tests/nstest tests/nstest.cpp + ${CXX} ${TESTCXXFLAGS} -o tests/tcpsrvtest tests/tcpsrvtest.cpp + ${CXX} ${TESTCXXFLAGS} -o tests/tcpclitest tests/tcpclitest.cpp + ${CXX} ${TESTCXXFLAGS} -o tests/udprecvtest tests/udprecvtest.cpp + ${CXX} ${TESTCXXFLAGS} -o tests/udpsendtest tests/udpsendtest.cpp + ${CXX} ${TESTCXXFLAGS} -o tests/httptest tests/httptest.cpp + +debugtest: + ${CXX} ${TESTCXXFLAGS} -g -o tests/nstest tests/nstest.cpp + ${CXX} ${TESTCXXFLAGS} -g -o tests/tcpsrvtest tests/tcpsrvtest.cpp + ${CXX} ${TESTCXXFLAGS} -g -o tests/tcpclitest tests/tcpclitest.cpp + ${CXX} ${TESTCXXFLAGS} -g -o tests/udprecvtest tests/udprecvtest.cpp + ${CXX} ${TESTCXXFLAGS} -g -o tests/udpsendtest tests/udpsendtest.cpp + ${CXX} ${TESTCXXFLAGS} -g -o tests/httptest tests/httptest.cpp + diff --git a/NetSocket.o b/NetSocket.o deleted file mode 100644 index ae137c0..0000000 Binary files a/NetSocket.o and /dev/null differ diff --git a/NetworkException.o b/NetworkException.o deleted file mode 100644 index 0dd4f5a..0000000 Binary files a/NetworkException.o and /dev/null differ diff --git a/ServerSocket.cpp b/ServerSocket.cpp index 6cf605d..d69a1d9 100644 --- a/ServerSocket.cpp +++ b/ServerSocket.cpp @@ -3,18 +3,6 @@ #include 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; @@ -27,7 +15,7 @@ _size = 0; } else { _size = sfa._size; _tab = new std::string[_size]; -for(int i = 0; i < _size; i++) { +for(unsigned int i = 0; i < _size; i++) { _tab[i] = sfa._tab[i]; } } @@ -42,10 +30,10 @@ _tab = NULL; } void ServerFunctionArgs::addArgument(std::string arg) { -int newSize = _size+1; +unsigned int newSize = _size+1; std::string* newTab = NULL; newTab = new std::string[newSize]; -for(int i = 0; i < _size; i++) { +for(unsigned int i = 0; i < _size; i++) { newTab[i] = _tab[i]; } newTab[newSize-1] = arg; @@ -54,31 +42,29 @@ delete[] _tab; _tab = newTab; } -std::string ServerFunctionArgs::getArgument(int idx) { -if(idx < 0 or idx >= _size) { +std::string ServerFunctionArgs::getArgument(unsigned int idx) { +if(idx >= _size) { throw SocketException("Index out of bounds!"); } else { return _tab[idx]; } } -std::string ServerFunctionArgs::operator[](int idx) { +std::string ServerFunctionArgs::operator[](unsigned 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) { +void ServerSocket::startServer(ServerFunctionArgs& functionOutput ,ServerFunctionArgs& (*serverMain)(ServerFunctionArgs, ServerSocket*), ServerFunctionArgs functionInput, bool infinite, unsigned int iternum, int connectionLimit) { if(_protocol == "UDP") { throw SocketException("startServer() works only with TCP! Use send() and recv() methods to transfer data via UDP!"); } @@ -92,21 +78,34 @@ void ServerSocket::startServer(ServerFunctionArgs functionOutput ,ServerFunction if(sigaction(SIGCHLD, &_sa, NULL) == -1) { throw SocketException("Sigaction failed!"); } - while(condition()) { + if(infinite == true) { + while(true) { _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); + functionOutput = serverMain(functionInput, this); } } + } else { + for(unsigned int i = 0; i < iternum; i++) { + _newDescriptor = accept(_descriptor, (sockaddr*)&_their_addr, &_addr_size); + if(_newDescriptor == -1) { + throw NetworkException("accept", strerror(errno)); + } + if(!fork()) { + close(_descriptor); + functionOutput = serverMain(functionInput, this); + } + } + } } int ServerSocket::send(std::string msg, int flags) { if(_protocol == "TCP") { - int sr = ::send(_descriptor, msg.c_str(), msg.length(), flags); + int sr = ::send(_newDescriptor, msg.c_str(), msg.length(), flags); if(sr == -1) { throw NetworkException("send", strerror(errno)); } @@ -123,7 +122,7 @@ int ServerSocket::send(std::string msg, int flags) { int ServerSocket::recv(int flags) { if(_protocol == "TCP") { - int rr = ::recv(_descriptor, _buf, 99999, flags); + int rr = ::recv(_newDescriptor, _buf, 99999, flags); if(rr == -1) { throw NetworkException("recv", strerror(errno)); } else if(rr == 0) { diff --git a/ServerSocket.h b/ServerSocket.h index 17f9fb7..1583a3c 100644 --- a/ServerSocket.h +++ b/ServerSocket.h @@ -19,25 +19,12 @@ 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; + unsigned int _size; public: ServerFunctionArgs(); ///< A constructor. ServerFunctionArgs(ServerFunctionArgs& sfa); ///< \brief A copy constructor. @@ -45,10 +32,10 @@ ServerFunctionArgs(ServerFunctionArgs& sfa); ///< \brief A copy constructor. ~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. +std::string getArgument(unsigned 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. +std::string operator[](unsigned int idx); ///< \brief Operator[] returning the argument of given index number. ///< \param idx Index of the argument. ///< \return The argument. }; @@ -65,11 +52,12 @@ ServerSocket(std::string host, std::string service, std::string protocol); ///< ///< \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. +void startServer(ServerFunctionArgs& functionOutput ,ServerFunctionArgs& (*serverMain)(ServerFunctionArgs, ServerSocket*), ServerFunctionArgs functionInput, bool infinite, unsigned int iternum, 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 infinite Determines if server loop should be infinite. +///< \param iternum Number of accept() iterations for non-infinite loops. ///< \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. diff --git a/ServerSocket.o b/ServerSocket.o deleted file mode 100644 index f355339..0000000 Binary files a/ServerSocket.o and /dev/null differ diff --git a/SocketException.o b/SocketException.o deleted file mode 100644 index f0ba9ad..0000000 Binary files a/SocketException.o and /dev/null differ diff --git a/libnetsocketpp.so.0.1 b/libnetsocketpp.so.0.1 deleted file mode 100755 index dc1f648..0000000 Binary files a/libnetsocketpp.so.0.1 and /dev/null differ diff --git a/tests/httptest.cpp b/tests/httptest.cpp new file mode 100644 index 0000000..a3f8f49 --- /dev/null +++ b/tests/httptest.cpp @@ -0,0 +1,22 @@ +#include +#include +#include +#include "NetSocket++/NetSocketPP.h" +using namespace std; + +int main() { +try { +NetSocketPP::HTTPClientSocket socket("phitherek.mooo.com", "http", "/"); +NetSocketPP::HTTPReply reply; +cout << "Sent request: " << endl << socket.getRequest() << endl << "Request end" << endl; +reply = socket.getReply(); +cout << "Read content: " << endl << reply.getContent() << endl; +return EXIT_SUCCESS; +} catch (NetSocketPP::NetworkException &exc) { + cerr << "Network exception in main function: " << exc.what() << endl; + return 2; + } catch (NetSocketPP::SocketException &exc) { + cerr << "Library exception in main function: " << exc.what() << endl; + return 1; + } +} diff --git a/tests/nstest b/tests/nstest deleted file mode 100755 index 3e085e9..0000000 Binary files a/tests/nstest and /dev/null differ diff --git a/tests/nstest.cpp b/tests/nstest.cpp index 768f578..a1d7acf 100644 --- a/tests/nstest.cpp +++ b/tests/nstest.cpp @@ -1,6 +1,6 @@ #include #include -#include "../NetSocketPP.h" +#include "NetSocket++/NetSocketPP.h" using namespace std; int main() { diff --git a/tests/tcpclitest.cpp b/tests/tcpclitest.cpp new file mode 100644 index 0000000..ab28a66 --- /dev/null +++ b/tests/tcpclitest.cpp @@ -0,0 +1,24 @@ +#include +#include +#include +#include "NetSocket++/NetSocketPP.h" +using namespace std; + +int main() { +cout << "Message to send to server: " << endl; +string msg; +cin >> msg; +try { +NetSocketPP::ClientSocket socket("127.0.0.1", "3490", "TCP"); +socket.recv(0); +cout << "Server said: " << socket.get() << endl; +socket.send(msg, 0); +return EXIT_SUCCESS; +} catch (NetSocketPP::NetworkException &exc) { + cerr << "Network exception in main function: " << exc.what() << endl; + return 2; + } catch (NetSocketPP::SocketException &exc) { + cerr << "Library exception in main function: " << exc.what() << endl; + return 1; + } +} diff --git a/tests/tcpsrvtest.cpp b/tests/tcpsrvtest.cpp new file mode 100644 index 0000000..8876fcd --- /dev/null +++ b/tests/tcpsrvtest.cpp @@ -0,0 +1,42 @@ +#include +#include +#include +#include "NetSocket++/NetSocketPP.h" +using namespace std; + +NetSocketPP::ServerFunctionArgs& serverMain(NetSocketPP::ServerFunctionArgs args, NetSocketPP::ServerSocket* sck) { + static NetSocketPP::ServerFunctionArgs ret; + try { + sck->send(args[0], 0); + sck->recv(0); + ret.addArgument(sck->get()); + } catch (NetSocketPP::NetworkException &exc) { + cerr << "Network exception in server function: " << exc.what() << endl; + ret.addArgument("exception"); + } catch (NetSocketPP::SocketException &exc) { + cerr << "Library exception in server function: " << exc.what() << endl; + ret.addArgument("exception"); + } + return ret; +} + +int main() { +cout << "Server message: " << endl; +string msg; +cin >> msg; +try { +NetSocketPP::ServerSocket socket("0.0.0.0", "3490", "TCP"); +NetSocketPP::ServerFunctionArgs args; +NetSocketPP::ServerFunctionArgs ret; +args.addArgument(msg); +socket.startServer(ret, serverMain, args, false, 1, 5); +cout << "Server function returned: " << ret[0] << endl; +return EXIT_SUCCESS; +} catch (NetSocketPP::NetworkException &exc) { + cerr << "Network exception in main function: " << exc.what() << endl; + return 2; + } catch (NetSocketPP::SocketException &exc) { + cerr << "Library exception in main function: " << exc.what() << endl; + return 1; + } +} diff --git a/tests/udprecvtest.cpp b/tests/udprecvtest.cpp new file mode 100644 index 0000000..52965f2 --- /dev/null +++ b/tests/udprecvtest.cpp @@ -0,0 +1,20 @@ +#include +#include +#include +#include "NetSocket++/NetSocketPP.h" +using namespace std; + +int main() { +try { +NetSocketPP::ServerSocket socket("127.0.0.1", "4950", "UDP"); +socket.recv(0); +cout << "Receiver got: " << socket.get() << endl; +return EXIT_SUCCESS; +} catch (NetSocketPP::NetworkException &exc) { + cerr << "Network exception in main function: " << exc.what() << endl; + return 2; + } catch (NetSocketPP::SocketException &exc) { + cerr << "Library exception in main function: " << exc.what() << endl; + return 1; + } +} diff --git a/tests/udpsendtest.cpp b/tests/udpsendtest.cpp new file mode 100644 index 0000000..e4fa132 --- /dev/null +++ b/tests/udpsendtest.cpp @@ -0,0 +1,22 @@ +#include +#include +#include +#include "NetSocket++/NetSocketPP.h" +using namespace std; + +int main() { +cout << "Message to send to receiver: " << endl; +string msg; +cin >> msg; +try { +NetSocketPP::ClientSocket socket("127.0.0.1", "4950", "UDP"); +socket.send(msg, 0); +return EXIT_SUCCESS; +} catch (NetSocketPP::NetworkException &exc) { + cerr << "Network exception in main function: " << exc.what() << endl; + return 2; + } catch (NetSocketPP::SocketException &exc) { + cerr << "Library exception in main function: " << exc.what() << endl; + return 1; + } +}