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