Throwing exceptions

dev v0.1_beta
marcelb 2 years ago
parent 3bbfef613a
commit 31091dcbec
  1. 13
      README.md
  2. 20
      lib/tcp_socket.hpp
  3. 124
      src/tcp_socket.cpp
  4. 6
      test/client.cpp
  5. BIN
      test/client.o
  6. 8
      test/server.cpp

@ -0,0 +1,13 @@
# A simple TCP socket library for C++
Object-oriented implemented library for easy creation and management of TCP sockets.
## Features
- Client aplication
- Server aplication
- Timeout connection
- SSL certificate

@ -14,6 +14,11 @@
using namespace std; using namespace std;
/**
* Server klasa za TCP/IP soket
* Instanca se incijalizira kada pokrećemo server
*/
class server { class server {
public: public:
int sock; int sock;
@ -24,6 +29,11 @@ class server {
}; };
/**
* Klasa za konstrukciju i destrukciju SSL certifikata
* Pokreće se za server i client - (različiti konstruktori)
*/
class secure { class secure {
public: public:
SSL_CTX* fds; SSL_CTX* fds;
@ -34,6 +44,11 @@ class secure {
}; };
/**
* Klasa za definiranje TCP soketa kod klijentskih aplikacija
*/
class client { class client {
public: public:
int sock; int sock;
@ -47,6 +62,11 @@ class client {
}; };
/**
* Klasa za inicijalizaciju dolaznih veza
* Definira se na serverskom tipu aplikacija i predstavlja identifikator klijenta
*/
class comming { class comming {
public: public:
const server *srv; const server *srv;

@ -1,5 +1,9 @@
#include "../lib/tcp_socket.hpp" #include "../lib/tcp_socket.hpp"
/**
* Kontrustruktor varijable tipa server, prima port i limit za ograničenje liste klijenata na čekanju
*/
server::server (const ushort port, const uint limit) { server::server (const ushort port, const uint limit) {
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
@ -8,47 +12,59 @@ server::server (const ushort port, const uint limit) {
sock = socket(AF_INET, SOCK_STREAM, 0); sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock <= 0) { if (sock <= 0) {
printf("[ERROR] Ne mogu otvoriti defenirani TCP/IP socket!"); throw "[ERROR] Unable to open TCP socket ";
} }
int opt=1; int opt=1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) { if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {
printf("[ERROR] Ne mogu otvoriti defenirani TCP/IP socket!"); throw "[ERROR] Unable to set REUSEADDR or REUSEPORT on socket ";
} }
if (bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) { if (bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) {
printf("[ERROR] Ne mogu bindati defenirani TCP/IP socket!"); throw "[ERROR] Unable to bind socket ";
} }
if (listen(sock, limit) < 0) { if (listen(sock, limit) < 0) {
printf("[ERROR] Ne mogu defenirani listen za TCP/IP socket!"); throw "[ERROR] It is not possible to set the allowed number of waiting clients ";
} }
} }
/**
* Destruktor varijable tipa server
*/
server::~server () { server::~server () {
if (sock<=0) { if (sock<=0) {
printf ("[ERROR] Soket destruktor: već zatvoren soket!"); throw "[ERROR] The socket is already closed ";
} }
else if (close(sock) != 0) { else if (close(sock) != 0) {
printf ("[ERROR] Soket destruktor nije mogao zatvoriti soket!"); throw "[ERROR] Unable to close socket ";
} }
} }
/**
* Konstruktor varijable tipa secure za klijentske implementacije
*/
secure::secure() { secure::secure() {
fds = SSL_CTX_new(SSLv23_client_method()); fds = SSL_CTX_new(SSLv23_client_method());
if (!fds) { if (!fds) {
//throw "[ERROR] Creating SSL context "; throw "[ERROR] Creating SSL context ";
cout << endl << "[ERROR] Creating SSL context ";
} }
} }
/**
* Konstruktor varijable tipa secure za serverske implementacije
*/
secure::secure(const string cert, const string priv) { secure::secure(const string cert, const string priv) {
SSL_library_init(); SSL_library_init();
@ -58,33 +74,40 @@ secure::secure(const string cert, const string priv) {
// Create an SSL context // Create an SSL context
fds = SSL_CTX_new(SSLv23_server_method()); fds = SSL_CTX_new(SSLv23_server_method());
if (!fds) { if (!fds) {
// throw "[ERROR] Creating SSL context "; throw "[ERROR] Creating SSL context ";
cout << endl << "[ERROR] Creating SSL context ";
} }
// Load the server's certificate and private key files // Load the server's certificate and private key files
if (SSL_CTX_use_certificate_file(fds, cert.c_str(), SSL_FILETYPE_PEM) <= 0) { if (SSL_CTX_use_certificate_file(fds, cert.c_str(), SSL_FILETYPE_PEM) <= 0) {
// throw "[ERROR] Loading certificate file."; throw "[ERROR] Loading certificate file ";
cout << endl << "[ERROR] Loading certificate file.";
} }
if (SSL_CTX_use_PrivateKey_file(fds, priv.c_str(), SSL_FILETYPE_PEM) <= 0) { if (SSL_CTX_use_PrivateKey_file(fds, priv.c_str(), SSL_FILETYPE_PEM) <= 0) {
//throw "[ERROR] Loading private key file."; throw "[ERROR] Loading private key file ";
cout << endl << "[ERROR] Loading private key file.";
} }
} }
/**
* Destruktor varijable tipa secure
*/
secure::~secure () { secure::~secure () {
SSL_CTX_free(fds); SSL_CTX_free(fds);
} }
/**
* Konstruktor varijable tipa client
* Prima adresu, port, i opcijonalno dozvoljeno vrijeme čekanja servera
* i deskriptor datoteke SSL certifikat za sigurne komunikacije
*/
client::client(const string address, const ushort port, const uint timeout, SSL_CTX* securefds) { client::client(const string address, const ushort port, const uint timeout, SSL_CTX* securefds) {
sock = socket(AF_INET, SOCK_STREAM, 0); sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) { if (sock < 0) {
printf("[ERROR] Ne mogu otvoriti TCP/IP socket!"); throw "[ERROR] Unable to open TCP socket ";
} }
const string _address = isIPAddress(address) ? address : ipFromDomain(address); const string _address = isIPAddress(address) ? address : ipFromDomain(address);
@ -94,23 +117,21 @@ client::client(const string address, const ushort port, const uint timeout, SSL_
addr.sin_port = htons(port); addr.sin_port = htons(port);
if (connect(sock, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)) != 0) { if (connect(sock, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)) != 0) {
printf("[EROR] Ne mogu se povezati s poslužiteljem!"); throw "Unable to connect to server ";
} }
struct timeval tv; struct timeval tv;
tv.tv_sec = 0; // za sad 2 sekunde timeout, harkodirano tv.tv_sec = 0;
tv.tv_usec = timeout*1000; tv.tv_usec = timeout*1000;
if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval))) { if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval))) {
printf ("[ERROR] 503 Ne mogu postaviti timeout!"); throw "[ERROR] Unable to set timeout ";
sock = -1;
} }
if (securefds) { if (securefds) {
ssl = SSL_new(securefds); ssl = SSL_new(securefds);
if (!ssl) { if (!ssl) {
//throw "[ERROR] Creating SSL object."; throw "[ERROR] Creating SSL object ";
cout << endl << "[ERROR] Creating SSL object.";
} }
SSL_set_fd(ssl, sock); SSL_set_fd(ssl, sock);
@ -118,13 +139,16 @@ client::client(const string address, const ushort port, const uint timeout, SSL_
// Perform the SSL handshake // Perform the SSL handshake
if (SSL_connect(ssl) <= 0) { if (SSL_connect(ssl) <= 0) {
SSL_free(ssl); SSL_free(ssl);
// throw "[ERROR] Performing SSL handshake."; throw "[ERROR] Performing SSL handshake ";
cout << endl << "[ERROR] Performing SSL handshake.";
} }
} }
/**
* Destruktor varijable tipa client
*/
client::~client () { client::~client () {
if (ssl) { if (ssl) {
@ -133,15 +157,21 @@ client::~client () {
} }
if (sock <= 0) { if (sock <= 0) {
printf ("[ERROR] Soket destruktor: već zatvoren soket!"); throw "[ERROR] The socket is already closed ";
} }
else if (close(sock) != 0) { else if (close(sock) != 0) {
printf ("[ERROR] Soket destruktor nije mogao zatvoriti soket!"); throw "[ERROR] Unable to close socket ";
} }
} }
/**
* Metoda klase client za slanje podataka preko soketa
* Prima string koji će biti poslan
* Vraća logički statu poređenja psolanih karaktera i karaktera u stringu
*/
bool client::tell (const string msg) { bool client::tell (const string msg) {
size_t sended = 0; size_t sended = 0;
@ -154,6 +184,12 @@ bool client::tell (const string msg) {
return sended == msg.length(); return sended == msg.length();
} }
/**
* Metoda klase client za primanje poruke preko soketa
* Prima dozvoljeni broj karaktera koji će primiti
* Vraća string primljene poruke
*/
string client::obey (size_t byte_limit) { string client::obey (size_t byte_limit) {
char res[byte_limit] = {0}; char res[byte_limit] = {0};
@ -167,6 +203,12 @@ string client::obey (size_t byte_limit) {
return (string) res; return (string) res;
} }
/**
* Konstruktor varijable tipa commint
* Prima pokazivač na inicijaliziranu varijablu tipa, port,
* i opcijonalno dozvoljeno vrijeme čekanja servera i deskriptor datoteke
* SSL certifikat za sigurne komunikacije
*/
comming::comming(const server *_srv, const uint timeout, SSL_CTX* securefds) { comming::comming(const server *_srv, const uint timeout, SSL_CTX* securefds) {
@ -174,7 +216,7 @@ comming::comming(const server *_srv, const uint timeout, SSL_CTX* securefds) {
socklen_t len = sizeof(struct sockaddr_in); socklen_t len = sizeof(struct sockaddr_in);
if ((conn = accept(srv->sock, (struct sockaddr *)&(srv->addr), (socklen_t*)&len)) < 0) { if ((conn = accept(srv->sock, (struct sockaddr *)&(srv->addr), (socklen_t*)&len)) < 0) {
printf("[ERROR] Ne mogu preuzeti vezu klijenta!"); throw "[ERROR] Unable to accept client connection ";
} }
struct timeval tv; struct timeval tv;
@ -182,23 +224,20 @@ comming::comming(const server *_srv, const uint timeout, SSL_CTX* securefds) {
tv.tv_usec = 0; tv.tv_usec = 0;
if (setsockopt(conn, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval))) { if (setsockopt(conn, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval))) {
printf("[ERROR] 503 Ne mogu postaviti timeout!"); throw "[ERROR] Unable to set timeout ";
conn = -1;
} }
if (securefds) { if (securefds) {
ssl = SSL_new(securefds); ssl = SSL_new(securefds);
if (!ssl) { if (!ssl) {
// throw "[ERROR] Creating SSL object."; throw "[ERROR] Creating SSL object ";
cout << endl << "[ERROR] Creating SSL object.";
} }
SSL_set_fd(ssl, conn); SSL_set_fd(ssl, conn);
// Perform SSL handshake // Perform SSL handshake
if (SSL_accept(ssl) <= 0) { if (SSL_accept(ssl) <= 0) {
SSL_free(ssl); SSL_free(ssl);
// throw "[ERROR] Performing SSL handshake."; throw "[ERROR] Performing SSL handshake ";
cout << endl << "[ERROR] Performing SSL handshake.";
} }
} }
@ -213,6 +252,10 @@ comming::comming(const server *_srv, const uint timeout, SSL_CTX* securefds) {
} }
/**
* Destruktor varijable tipa comming
*/
comming::~comming() { comming::~comming() {
if (ssl) { if (ssl) {
@ -221,14 +264,20 @@ comming::~comming() {
} }
if (conn <= 0) { if (conn <= 0) {
printf ("[ERROR] Comming destruktor: već zatvoren soket!"); throw "[ERROR] The socket is already closed ";
} }
else if (close(conn) != 0) { else if (close(conn) != 0) {
printf ("[ERROR] Comming destruktor nije mogao zatvoriti soket!"); throw "[ERROR] Unable to close socket ";
} }
} }
/**
* Metoda klase comming za slanje podataka preko soketa
* Prima string koji će biti poslan
* Vraća logički statu poređenja psolanih karaktera i karaktera u stringu
*/
bool comming::tell (const string msg) { bool comming::tell (const string msg) {
ssize_t sended = 0; ssize_t sended = 0;
if (ssl) { if (ssl) {
@ -240,6 +289,13 @@ bool comming::tell (const string msg) {
return sended == msg.length(); return sended == msg.length();
} }
/**
* Metoda klase comming za primanje poruke preko soketa
* Prima dozvoljeni broj karaktera koji će primiti
* Vraća string primljene poruke
*/
string comming::obey (size_t byte_limit) { string comming::obey (size_t byte_limit) {
char res[byte_limit] = {0}; char res[byte_limit] = {0};

@ -6,12 +6,18 @@ using namespace std;
int main() { int main() {
try {
secure crypto; secure crypto;
client myserver("localhost", 5000, 500, crypto.fds); client myserver("localhost", 5000, 500, crypto.fds);
string sends = "Hello world!"; string sends = "Hello world!";
cout << myserver.tell(sends) << " " << sends.length() << endl; cout << myserver.tell(sends) << " " << sends.length() << endl;
cout << myserver.obey(); cout << myserver.obey();
}
catch (const string err) {
cout << err << endl;
}
return 0; return 0;
} }

Binary file not shown.

@ -5,7 +5,7 @@
using namespace std; using namespace std;
int main() { int main() {
try{
cout << "init server " << endl; cout << "init server " << endl;
server myserver(5000, 10); server myserver(5000, 10);
cout << "init cert " << endl; cout << "init cert " << endl;
@ -31,7 +31,9 @@ int main() {
// } // }
// sleep(80); // sleep(80);
}
catch(const string err) {
cout << err << endl;
}
return 0; return 0;
} }
Loading…
Cancel
Save