I have been working on a small project which is a SMTP client written in C with SSL.
I am trying to get it working with GMail. I have enabled the allow unsecure apps in GMail settings.
When I try to authenticate using the OpenSSL CLI with the command openssl s_client -connect smtp.gmail.com:465 it works just fine I get proper responses for HELO and EHLO commands (see the output below)
220 smtp.gmail.com ESMTP o3-v6sm18136158pgv.53 - gsmtp
HELO smtp.gmail.com
250 smtp.gmail.com at your service
AUTH LOGIN
334 VXNlcm5hbWU6
But once I run this with my C client it hangs on SSL_read after I send HELO smtp.gmail.com and it does not even give me any output for HELO smtp.gmail.com.
But if I send just HELO I get a proper response from the server saying that empty HELO isn't allowed
MAIN
int main(int argc, char **argv) {
setup("smtp.gmail.com", 465);
printf("[INFO] -- %s\n", recv_secure());
send_secure("HELO smtp.gmail.com\r\n");
printf("[INFO] -- %s\n", recv_secure());
send_secure("AUTH LOGIN\r\n");
printf("[INFO] -- %s\n", recv_secure());
close_secure();
return 0;
}
setup
int setup(char *hostname, int port) {
SSL_CTX *ctx = init();
struct hostent *host;
struct sockaddr_in addr;
int sock_fd;
if((host = gethostbyname(hostname)) == NULL) {
fprintf(stderr, "[ERROR] Unable to get host by name: %s", hostname);
return -1;
}
sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = *(long*)host->h_addr_list[0];
if(connect(sock_fd, (struct sockaddr*) &addr, sizeof(addr)) != 0) {
close(sock_fd);
fprintf(stderr, "[ERROR] Unable to connect to remote server: %s\n", hostname);
return -1;
}
ssl = SSL_new(ctx);
SSL_set_fd(ssl, sock_fd);
if(SSL_connect(ssl) == -1) {
fprintf(stderr, "[ERROR] Unable to establish secure connection\n");
close(sock_fd);
return -1;
}
return sock_fd;
}
send_secure
void send_secure(const char* buffer){
SSL_write(ssl, buffer, sizeof(buffer));
}
recv_secure
char* recv_secure() {
int bytes = SSL_read(ssl, rbuffer, SIZE);
rbuffer[bytes] = 0;
fprintf(stderr, "[DEBUG] -- Received: %s\n", rbuffer);
return rbuffer;
}
I ran ltrace with it and it seems to be blocked at SSL_read but SSL_pending return value is 0
I cannot seem to understand what am I missing here.
void send_secure(const char* buffer){
SSL_write(ssl, mbuffer, sizeof(mbuffer));
}
Assuming that mbuffer is a typo and buffer was meant instead, this will write either 8 or 4 bytes (the size of a pointer, depending on your platform), not the length of the buffer as you probably expected (which will be wrong, too since sizeof, when applied to a literal string, also includes the terminating null byte -- which will NOT be accepted by the smtp server).
Changing sizeof to strlen may let you proceed further, but your code has a lot of problems, for instance:
int bytes = SSL_read(ssl, rbuffer, SIZE);
rbuffer[bytes] = 0;
If SSL_read returns -1, this will (in the best case ;-)) crash your program.
Related
I am looking to download or read a file from a server over HTTPS, and I'm using openSSL for it.
I see the connection succeeds, however SSL_read() returns 0. SSL_get_error() returns 6 which refers to SSL_ERROR_ZERO_RETURN macro and seems to be a normal behavior but I'm not sure why was the connection shutdown while something was being read? And this might be why it's reading 0 bytes?
#define CHECK_NULL(x) if ((x)==NULL) exit (1)
#define CHECK_ERR(err,s) if ((err)==-1) { perror(s); exit(1); }
#define CHECK_SSL(err) if ((err)==-1) { ERR_print_errors_fp(stderr); exit(2); }
void ServerConnectAndRcv(uint8_t *str)
{
int err;
int sd;
struct sockaddr_in sa;
SSL_CTX* ctx;
SSL* ssl;
char* str;
char buf [4096];
const SSL_METHOD *meth;
SSLeay_add_ssl_algorithms();
meth = TLSv1_2_client_method();
SSL_load_error_strings();
ctx = SSL_CTX_new (meth);
SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
// create a socket and connect to the server
sd = socket (AF_INET, SOCK_STREAM, 0);
CHK_ERR(sd, "socket");
memset (&sa, '\0', sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = inet_addr (<SERVER-IP>); /* Server IP */
sa.sin_port = htons (<SERVER-PORT>); /* Server Port number */
ssl = SSL_new (ctx);
CHECK_NULL(ssl);
SSL_set_fd (ssl, sd);
err = SSL_connect (ssl);
CHECK_SSL(err);
// read from the server
err = SSL_read (ssl, buf, sizeof(buf) - 1);
CHECK_SSL(err);
if (err <= 0)
{
printf ("Error reading: %d\n", SSL_get_error(ssl, err));
}
buf[err] = '\0';
printf ("Received % bytes\n", err); // Received 0 bytes
SSL_shutdown (ssl);
}
As one of the commenters pointed out, I needed to send a GET request to be able to receive a response back from the server.
I sent pszResourcePath via SSL_write() and SSL_read() read the entire response just fine.
char pszRequest[100]= {0};
char pszResourcePath[]="<resourcePath>";
char pszHostAddress[]="<serverIP>";
sprintf(pszRequest, "GET /%s HTTP/1.1\r\nHost: %s\r\nConnection: Keep-Alive\r\n\r\n", pszResourcePath, pszHostAddress);
I'm trying to learn C sockets right now by making a simple web scraper, but doing the socket programming and HTTP requests myself, currently using socket libraries. I've written a function that successfully sends a non-SSL request to http://mirror.vcu.edu and stores the output in a variable called response.
char *noSSLRequest(REQUEST_HEADER_INFO *request_header_info) {
struct sockaddr_in serverAddress;
char *requestHeader;
unsigned short serverPort;
char serverIP[13];
domainToIP(request_header_info->host, serverIP);
char *response = calloc(0, 0);
ssize_t bytesReceived = 0;
int sockFD; //Only supporting IPV4 right now, returns file descriptor for socket
if ((sockFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < -1) {
freeRequestHeaderInfo(request_header_info);
fprintf(stderr, "Error, could not open socket in http.c getHTMLBody(). Reason for error %s", strerror(errno));
exit(-1);
}
printf(ANSI_COLOR_GREEN "LOG: Socket file descriptor is %d" ANSI_COLOR_RESET, sockFD);
serverPort = 80;
memset(&serverAddress, 0, sizeof(serverAddress));
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(80);
inet_aton(serverIP, &serverAddress.sin_addr);
if (connect(sockFD, (const struct sockaddr *) &serverAddress, sizeof(serverAddress)) < 0) {
freeRequestHeaderInfo(request_header_info);
fprintf(stderr, "Error, could not connect socket in http.c getHTMLBody(). Reason for error %s",
strerror(errno));
exit(-1);
}
printf(ANSI_COLOR_GREEN "\nLOG: Connected socket at descriptor %d to IP %s and port %d" ANSI_COLOR_RESET, sockFD,
serverIP, serverPort);
requestHeader = craftRequestHeader(request_header_info);
if (send(sockFD, requestHeader, strlen(requestHeader), 0) < 0) {
freeRequestHeaderInfo(request_header_info);
fprintf(stderr, "Error, could not send request. Reason for error %s",
strerror(errno));
exit(-1);
}
printf(ANSI_COLOR_GREEN "\nLOG: Sent HTTP request from socket at descriptor %d to IP %s and port %d." ANSI_COLOR_RESET,
sockFD,
serverIP, serverPort);
free(requestHeader);
printf(ANSI_COLOR_GREEN "\nLOG: Starting receive operation" ANSI_COLOR_RESET);
ssize_t bytesReceivedPrevious = -1;
char buffer[RESPONSE_BUFFER_SIZE];
while (bytesReceived < (RESPONSE_MAX_LEN * sizeof(char)) && bytesReceived > bytesReceivedPrevious) {
bytesReceivedPrevious = bytesReceived;
bytesReceived = recv(sockFD, buffer, RESPONSE_BUFFER_SIZE, 0);
response = realloc(response, sizeof(*response) + RESPONSE_BUFFER_SIZE);
strcat(response, buffer); //Append to the end, safe because recv takes care of limiting buffer size
}
response = realloc(response, sizeof(*response) + sizeof(char));
response[strlen(response)] = '\0';
printf(ANSI_COLOR_GREEN "\nLOG: Received HTTP response from socket at descriptor %d to IP %s and port %d.\n\n\n\n\n" ANSI_COLOR_RESET,
sockFD,
serverIP, serverPort);
if (close(sockFD) < 0) {
freeRequestHeaderInfo(request_header_info);
fprintf(stderr, "Error, could not close socket in http.c getHTMLBody(). Reason for error %s", strerror(errno));
exit(-1);
}
printf(ANSI_COLOR_GREEN "\nLOG: Closed socket at descriptor %d" ANSI_COLOR_RESET, sockFD);
freeRequestHeaderInfo(request_header_info);
return response;
}
Everything works fine, response has a null terminator and life is good, except that in my console, for some reason, I'm getting the output of response printed out. I feel like something is leaking somewhere, because this output is in green as well even though after every log I am resetting the color back to default. I know some of the flags and other stuff up there is not shown, I couldn't get all the info and code here so I have a github repo and more detailed issue.
Picture of log is on here and on the issue, though I couldn't get the full output so the non-coloured text version is on the issue.
This code
response = realloc(response, sizeof(response) + RESPONSE_BUFFER_SIZE);
and this code
response = realloc(response, sizeof(response) + sizeof(char));
both cause undefined behavior.
response is a char * - a pointer. sizeof() a pointer is the size of the pointer, not the length of the string it points to.
Note also that sizeof(char) is one by definition.
I'm a newbie in Network Programming, started to learn how to use WinSock in C.
I don't have any knowledge in Networking right now.
Anyway, I've written the following code for Client and Server, using WinSock.
Server:
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#define MY_ERROR 1
#define PORT 7777
#define MAX_NUM_CLIENTS 1 /* I don't know how to thread right now. */
#define MAX_CLIENT_MSG_LEN 1000
int main()
{
WSADATA wsa;
SOCKET mySocket, acceptSocket;
struct sockaddr_in server, client;
int sockAddrInLength = sizeof(struct sockaddr_in);
char clientMessage[MAX_CLIENT_MSG_LEN];
int clientMessageLength;
char* message;
int running = 1;
if(WSAStartup(MAKEWORD(2,2), &wsa) != 0)
{
fprintf(stderr, "WSAStartup failed.\n");
return MY_ERROR;
}
printf("WSAStartup succeded.\n");
mySocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (mySocket == INVALID_SOCKET)
{
fprintf(stderr, "Socket creation failed.\n");
return MY_ERROR;
}
printf("Socket creation succeeded.\n");
server.sin_addr.s_addr = INADDR_ANY;
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
if (bind(mySocket, (struct sockaddr*) &server, sizeof server) == SOCKET_ERROR)
{
fprintf(stderr, "Binding socket on port %d failed.\n", PORT);
return MY_ERROR;
}
printf("Binding socket on port %d successfully.\n", PORT);
while (running)
{
listen(mySocket, MAX_NUM_CLIENTS);
printf("Waiting for a connection...\n");
acceptSocket = accept(mySocket, (struct sockaddr*) &client, &sockAddrInLength);
if (acceptSocket == INVALID_SOCKET)
{
fprintf(stderr, "Accept failed.\n");
return MY_ERROR;
}
printf("Accept succeeded.\n");
if ((clientMessageLength = recv(acceptSocket, clientMessage, sizeof clientMessage, 0)) == SOCKET_ERROR)
{
fprintf(stderr, "Recv failed.\n");
return MY_ERROR;
}
printf("Recv succeeded.\n");
printf("Data:\n");
clientMessage[clientMessageLength] = NULL; /* Null terminator */
printf("Client: %s\n", clientMessage);
message = "Hello client, I'm the server. Bye bye. :-)\n";
if (send(acceptSocket, message, strlen(message), 0) < 0)
{
fprintf(stderr, "Send failed.\n");
return MY_ERROR;
}
printf("Send succeded.\n");
}
closesocket(mySocket);
WSACleanup();
getchar();
return 0;
}
And this is the code for the Client:
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#define IP /* My IP */
#define MY_ERROR 1
#define PORT 7777
#define MAX_SERVER_MSG_LEN 1000
int main()
{
WSADATA wsa;
SOCKET mySocket;
struct sockaddr_in server;
char* message;
char serverMessage[MAX_SERVER_MSG_LEN];
int serverMessageLength;
if(WSAStartup(MAKEWORD(2,2), &wsa) != 0)
{
fprintf(stderr, "WSAStartup failed.\n");
getchar();
return MY_ERROR;
}
printf("WSASucceeded.\n");
mySocket = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);
if (mySocket == INVALID_SOCKET)
{
fprintf(stderr, "Socket creation failed.\n");
getchar();
return MY_ERROR;
}
server.sin_addr.s_addr = inet_addr(IP);
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
if (connect(mySocket, (struct sockaddr*) &server, sizeof server) < 0)
{
fprintf(stderr, "Connection failed. error: %s\n",WSAGetLastError());
getchar();
return MY_ERROR;
}
printf("Connection established.\n");
message = "Hello server, I'm the sweet client. :-)\n";
if (send(mySocket, message, strlen(message), 0) < 0)
{
fprintf(stderr, "Sending failed.\n");
return MY_ERROR;
}
printf("Sending succeeded.\n");
if ((serverMessageLength = recv(mySocket, serverMessage, sizeof serverMessage, 0)) == SOCKET_ERROR)
{
fprintf(stderr, "Recv failed.\n");
return MY_ERROR;
}
printf("Recv succeeded.\n");
printf("Data:\n");
serverMessage[serverMessageLength] = NULL;
printf("Server: %s", serverMessage);
closesocket(mySocket);
getchar();
return 0;
}
Ok.
When I run both server and client on my comupter, and define IP (in the client code) to be my internal IP (I think, becuase it is the form of 192.168.x.x) it works fine.
When I define IP to be my external IP, it doesn't work on my computer (when I run both program in my computer). The connection failes.
In addition -
When I'm trying to run the client on any other computer, it doesn't work (when IP is defined to be my internal or my external IP), the connection failes.
My questions are:
Why when I run both server & client on my computer, it works just with my internal IP?
What should I do in order that the client could be run on another computer and it will work?
I know that maybe the answer contains terms like "internal/external IPs", "routers", maybe "firewall" or "port forwarding".
Just remember I'm really a newbie in Networking and I don't have any knowledge about those terms, so please: I hope your explnations will be beginner-friendly.
I want to start learning Networking, but my first step is to understand how to use Sockets, and I have a problem in the connetction with other computers.
If you have any articles/something like that in order to give me a better understanding of the problem, it could help too.
Thank you very much! :)
This doesn't look like a coding problem, but a network configuration problem.
Let me try and rephrase what you're saying : Please correct me if I've misunderstood:-
You have an "internal" network (192.168.x.y).
You run the client on one PC on your internal network, and the server on another.
It all works so far.
But, you're also connected to the internet, via a different 'external' IP address
- When your client tries to access the server via this address, it fails. (The exact error code from WSAGetLastError is useful here, please)
At this point, it's down to how you're connected to the net. Let's assume a typical home office scenario. You have broadband, with an ADSL router/modem giving you network connectivity. Now, while the router will have an 'external' IP address, PC's on your local network typically do NOT. So, if you try connecting to the 'external' IP, you're actually trying to talk to the router.
This is where Port forwarding comes into play. You need to configure the router to forward port 7777 to the correct IP address for your server on the internal network. You'll find a screen like this on your router somewhere.
You would enter port 7777 for both 'from' and 'to', enable TCP, and specify the LAN address of your server. The router will then forward incoming connections on port 7777 to the specified server.
I have written a simple SSL Client/Server set of programs from a few tutorials I have found on the net - and these work fine. What I cant get my head around is the client side of things (See below)
It looks as if from the code the client connects to the SSL server, blindly accepts the certificate it provides then then uses it to encrypt/decrypt the data sent to and from the pair.
Should there not be something client side that validates the servers certificate for use? I mean I can change / swap the server side certificate with any new one and have it connect without so much as a wimper? How is this a secure method of connection? (or am I - as I suspect - missing something )
Many thanks
FR
void LoadCertificates(SSL_CTX* ctx, char* CertFile, char* KeyFile);
int OpenConnection(const char *hostname, int port);
void ShowCerts(SSL* ssl);
SSL_CTX* InitCTX(void);
int main(int count, char *strings[]) {
char *hostname, *portnum;
char buf[1024];
SSL_CTX *ctx;
SSL *ssl;
int server;
int bytes;
if ( count != 3 ) {
printf("usage: %s <hostname> <portnum>\n", strings[0]);
exit(0);
} // if
hostname=strings[1];
portnum=strings[2];
printf("\nSSL Client 0.1\n~~~~~~~~~~~~~~~\n\n");
// Init. the SSL lib
SSL_library_init();
ctx = InitCTX();
printf("Client SSL lib init complete\n");
// Open the connection as normal
server = OpenConnection(hostname, atoi(portnum));
// Create new SSL connection state
ssl = SSL_new(ctx);
// Attach the socket descriptor
SSL_set_fd(ssl, server);
// Perform the connection
if ( SSL_connect(ssl) != FAIL ) {
char *msg = "Here is some data";
printf("Connected with %s encryption\n", SSL_get_cipher(ssl));
// Print any certs
ShowCerts(ssl);
// Encrypt & send message */
SSL_write(ssl, msg, strlen(msg));
// Get reply & decrypt
bytes = SSL_read(ssl, buf, sizeof(buf));
buf[bytes] = 0;
printf("Received: '%s'\n\n", buf);
// Release connection state
SSL_free(ssl);
} // if
else ERR_print_errors_fp(stderr);
// Close socket
close(server);
// Release context
SSL_CTX_free(ctx);
return 0;
} // main
SSL_CTX* InitCTX(void) {
SSL_METHOD const *method;
SSL_CTX *ctx;
// Load cryptos, et.al.
OpenSSL_add_all_algorithms();
// Bring in and register error messages
SSL_load_error_strings();
// Create new client-method instance
method = SSLv3_client_method();
// Create new context
ctx = SSL_CTX_new(method);
if ( ctx == NULL ) {
ERR_print_errors_fp(stderr);
abort();
} // if
return ctx;
} //InitCTX
int OpenConnection(const char *hostname, int port) {
int sd;
struct hostent *host;
struct sockaddr_in addr;
if ( (host = gethostbyname(hostname)) == NULL ) {
perror(hostname);
abort();
} // if
sd = socket(PF_INET, SOCK_STREAM, 0);
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = *(long*)(host->h_addr);
if ( connect(sd, (struct sockaddr*)&addr, sizeof(addr)) != 0 ) {
close(sd);
perror(hostname);
abort();
} // if
return sd;
} // OpenConnection
void ShowCerts(SSL* ssl) {
X509 *cert;
char *line;
cert = SSL_get_peer_certificate(ssl); /* get the server's certificate */
if ( cert != NULL ) {
printf("\nServer certificate:\n");
line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
printf("Subject: %s\n", line);
// Free the malloc'ed string
free(line);
line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
printf("Issuer: %s\n", line);
// Free the malloc'ed string
free(line);
// Free the malloc'ed certificate copy
X509_free(cert);
} // if
else printf("No certificates.\n");
} // ShowCerts
You are correct. The connection is secure (from eavesdropping), has integrity (protection against injection, truncation, and modification), and authentication (peer is who he says he is in his certificate), all done automatically for you by the transport, but it still lacks authorization (is this the person I wanted to talk to, and what exactly is this person allowed to do in my application). Only the application can do that, inherently, so it is up to you to get the peer certificate, get its SubjectDN, relate that to some local user database, check for existence, check its roles, etc.
A "Secure Connection" can be seen as consisting of two things:
1 Authentication: Be sure to be connected to the partner (here: server) one expects to connect to
2 Encryption: Have the data (transferred by the connection) be protected against being read during transmission
The certificate received from the server can be used to accomplish 1. The certificate is not necessarily involved in 2.
On how to add verification of a server's certificate to your client, you might like to check out this SO answer: https://stackoverflow.com/a/12245023/694576 (which you could have done in the first place anyway ... ;->)
For details on TLS (successor to SSL and former SSL 3.x) please see here: http://en.wikipedia.org/wiki/Transport_Layer_Security
I am trying to implement a simple countdown application in C using UDP sockets.
I have a very strange problem with the server part of the application: it should receive a number from a client and then send different numbers for the countdown. So if, for example, a user types 5 in the client, then the server should receive 5 and send 4, 3, 2, 1 and 0 to the client. Here's my code:
#define BUFFERSIZE 512
#define PORT 55123
void ClearWinSock()
{
#if defined WIN32
WSACleanup();
#endif
}
int main()
{
#if defined WIN32
WSADATA wsaData;
WORD wVersionRequested;
wVersionRequested = MAKEWORD(2, 2);
if(WSAStartup(wVersionRequested, &wsaData) != 0)
{
printf("Error: unable to initialize the socket!\n");
return -1;
}
#endif
int mainSocket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(mainSocket < 0)
{
printf( "Error: unable to create the socket!\n");
ClearWinSock();
return -1;
}
struct sockaddr_in serverSockAddrIn;
memset(&serverSockAddrIn, 0, sizeof(serverSockAddrIn));
serverSockAddrIn.sin_family = AF_INET;
serverSockAddrIn.sin_port = htons(PORT);
serverSockAddrIn.sin_addr.s_addr = inet_addr("127.0.0.1");
if(bind(mainSocket, (struct sockaddr*) &serverSockAddrIn, sizeof(serverSockAddrIn)) < 0)
{
fprintf(stderr, "Error: unable to bind the socket!\n");
ClearWinSock();
return -1;
}
char buffer[BUFFERSIZE];
struct sockaddr_in clientAddress;
unsigned int clientAddressLength;
int recvMessageSize;
while(1)
{
clientAddressLength = sizeof(clientAddress);
recvMessageSize = recvfrom(mainSocket, buffer, BUFFERSIZE, 0, (struct sockaddr*) &clientAddress, &clientAddressLength);
int countdownValue;
sscanf(buffer, "%d", &countdownValue);
printf("\nNumber received: %d\n", countdownValue);
int index;
for(index = countdownValue - 1; index >= 0; --index)
{
itoa(index, buffer, 10);
int outputStringLength = strlen(buffer);
if(sendto(mainSocket, buffer, outputStringLength, 0, (struct sockaddr*) &clientAddress, sizeof(clientAddress)) != outputStringLength)
{
printf("Error: unable to send the message!");
}
}
}
ClearWinSock();
return 0;
}
Now the problem is that if I, for example, send the number 5 from the client, sometimes the server works correctly and sometimes it says "Number received: 5", doesn't send anything and then it says "Number received: 0" for 5 times.
I think I am doing something wrong in using the sockets. Or maybe it's something which involves cleaning the buffer, don't know! I can't reproduce the error because with the same input sometimes it acts in a way and sometimes in the other.
Are both your client and your server both listening on the same port? If so, you might want to consider having them listen on different ports (e.g. client sends to X and listens to port Y; server sends to port Y and listens to port X) so that they don't interfere with each other or accidentally receive their own sent-packets when both client and server are running on the same host.
Alternatively, you can instruct both client and server to share the same port by always executing the following code before calling bind():
const int trueValue = 1;
setsockopt(mainSocket, SOL_SOCKET, SO_REUSEADDR, (const char *) &trueValue, sizeof(trueValue));