SSL_connect succeeding but returning -1 - c

I'm trying to do a https connection over TLSv1.2. Context creation and everything is fine which I've not included in the below code.
if(https) //block 1
{
int ssl_err = 0;
int ssl_rc = 0;
ssl_fd = SSL_new(ctx); /* create new SSL connection state */
if(ssl_fd) //block 2
{
printf("Failure in SSL state creation.");
ssl_err = -1;
}
if(ssl_err == 0) //block 3
{
SSL_set_fd(ssl_fd, fd); /* attach the socket descriptor */
ERR_clear_error();
ssl_rc = SSL_connect(ssl_fd); /* perform the connection*/
printf("Failure in SSL connection %d returned.\n", ssl_rc);
if ( ssl_rc == -1 ) //block 4
ssl_err = -1;
}
if ( ssl_err == -1 ) //block 5
{
printf("Failure in SSL connection.\n");
SSL_free(ssl_fd);
shutdown(fd, 2);
abort();
}
}
In the code above, it's showing output as
Failure in SSL connection -1 returned.
Failure in SSL connection.
I've checked the packets file. Immediately (in 200 microseconds) after sending the client hello, it is going to if block 5 and sending a FIN request which kept me worried to find the error which I couldn't as without server's response, the SSL_connect is returning with error.
I commented if block 5 and tested. To my surprise, since the shutdown is not called, the SSL handshake is happening and data transfer over TLSv1.2 is going on till the end. That means SSL_connect is actually succeeding but somehow it's happening async. But in this way, I can't report if actually there is some errors in the SSL handshaking.
Can anyone help me with this behaviour?
Whether it's actually doing the handshake asynchronously? If yes, why it's returning -1 immediately. Shouldn't it wait for the handshake to complete before putting -1?

As you mentioned you have non-blocking sockets. In that case if SSL_connect() returns -1you need to call SSL_get_error(), check what it returns SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, then call SSL_connect() again after checking the underlying socket is ready for read/write with select()

Related

Client/server chatroom: Handle unexpected disconnect

I wrote in C a server - client chatroom.
The server creates a new pthread for every new connection to a client, this pthread waits for a message to receive, and sends this message to all the other clients (using a array of all the file descriptors). If a client wants to quit he informs the server and he will terminate the pthread and delete the file descriptor from the array
This works fine !, but:
if a client disconnects unexpected, by closing the terminal for example, the server won't delete the file descriptor from the array and when an other client wants to send a message i have an error because the pthread tries to send the message to a fd which isn't a connection any more
Now my question:
How can in test if the file descriptor of a client's socket is still active before i send a message ?
the part of my code (from the pthread):
for(i=0; i<*p_Nbr_Clients; i++){ // send the message to all the other clients
if (fd_array[i] != fd){ // <- i want to test the fd here
if ( send(fd_array[i], msg, strlen(msg), 0) == -1 ){
perror("Serveur: send");
}
}
}
Check the return value of the recv().
If the user terminated abnormally then return value should be zero 0.
Based on that you can close fd easily.
if(recv(fd,buffer,length,flag) == 0)
close(fd);
There is no standalone api to check whether socket is closed. Just try to send data to that socket.
send will return -1 if you write to a closed socket. and errno will be set to appropriately. You may got EBADF or ECONNRESET i guess. Check (Check connection open or closed ?(in C in Linux)) and (How to find out if a socket is closed)
for(i=0; i<*p_Nbr_Clients; i++){ // send the message to all the other clients
if (fd_array[i] != fd){ // <- i want to test the fd here
if ( send(fd_array[i], msg, strlen(msg), 0) == -1 ){
//perror("Serveur: send");
// something wrong, check errno to see more detail
// you need to include <errno.h> to use errno
close(fd_array[i]);
fd_array[i] = -1;// or something you define as not open
}
}
}

Accept call does'nt block the second time (or more than one time)?

I have the following code and I`m not sure why wont it work properly .
Its a multithreaded TCP server that loops accept() calls and triggers a designated
thread each time .
The problem is that the accept at times wont block , thus resulting
the program to open a new thread when there's theoretically no connection .
That's the loop -
for (dwI = 0;; dwI++) //Accept MAX_CLIENTS connections
{
if(MAX_CLIENTS == dwI)
{
dwI=0;
continue;
}//if
if(clients[dwI].bIsInUse)
{
continue;
}//if
ZeroMemory(&from,sizeof(from));
if(!AcceptConnection(&ServerSock,&from,&ClientSock))
{
PRINT_LE("AcceptConnection",ERROR_ACCEPT_SERVER_CONNECTION);
closesocket(ServerSock);
WSACleanup();
return EXIT_FAILURE;
}//if
clients[dwI].ClientSock = ClientSock;
if(! (clients[dwI].hThread = CreateThread(
NULL, //Not inheritable
0, //Default stack size
ThreadedAcceptTCP, //ThreadedAccept - function
&clients[dwI],//Pass pointer to the socket
0, //Start immidiately
&clients[dwI].dwThreadId //Save thread id
)))
{
PRINT_GLE("CreateThread");
closesocket(ServerSock);
WSACleanup();
return EXIT_FAILURE;
}//if
#ifdef PRINT_STATUS //Print status if macro is defined
printf("Server responce message has been sent.\n");
#endif
}//for
With my own wrappers to each function .
AcceptConnection has the code below -
SOCKET ClientSocket = INVALID_SOCKET; //Client socket
INT sockaddrSize = sizeof(*pSockAddr);
ClientSocket = accept( //Create client accepting socket
*pSock, //Listen-ed socket
pSockAddr,
&sockaddrSize
);
if (INVALID_SOCKET == ClientSocket) //Check for errors - if any - cleanup and return failure
{
PRINT_WSAGLE("socket");
return FAILURE;
}//if
*pClientSock = ClientSocket; //Pass socket
return SUCCESS;
The problem occurs when I connect to the server through my browser ,
for example ,
after the first thread is done (I`ve made this sure by temporarily sleeping the main thread for 5 seconds)
it cleans everything and closes the client socket ,
though on the second accept call - it will return with the same
SOCKADDR information and cause an extra thread to go up ,
receiving the exact same data , sending the exact same data .
And printing 2 (and at times even more) times :
"Server responce message has been sent."
I could'nt figure out why this happens and hopefully you guys could help me out .
Thanks !
This is a bit of a guess, but I wonder about the logic in this line of code:
if(!AcceptConnection(&ServerSock,&from,&ClientSock))
It is expecting AcceptConnection to return a non-zero value when it succeeds and a zero value when it fails. However, the function returns a constant SUCCESS when it succeeds. However, some of the Windows header files defined the constant SUCCESS to be 0. And various constants for failure are some non-zero value.
Even if you are defining SUCCESS and FAILURE in your own code, it might make sense to specifically check the return value such as:
if (FAILURE == AcceptConnection(&ServerSock,&from,&ClientSock))
One possible issue: it doesn't look like you are setting clients[dwI].bIsInUse to true after assigning a new client SOCKET, which will mess up your logic in your for loop.

TCP Connect error 115 Operation in Progress What is the Cause?

My application creats a TCP connection, This is working normaly.
But in one network server has many IP say
174.X.X.X
54.x.x.x
like this
When calling TCP connect (Non blocking with timeout of 60 seconds)
to IP 174.X.X.X is always success .
But TCP connect to same server with ip 54.x.x.x is failing (most of the times) with errno 115
measn operation in progress.
Can you please explain me what are the possible reason for errno 115
OS : Linux
My TCP conenct code is as below
tcp_connect(......)
{
int iValOpt = 0;
int iLength= 0;
fcnt((int)(long)SockID,F_SETFL_O_NONBLOCK);
ret = connect (sockID,(struct sockaddr*)pstSockAdr,uiSockLen);
if (ret < 0)
{
if (errno == EINPROGRESS)
{
stTv.tv_sec = 60;
stTv.tv_usec = 0;
FD_ZERO(&write_fd);
FD_SET(sockID,&write_fd);
iLength = sizeof(int);
if (0 < select (sockID+1) , NULL,&write_fd,NULL,&stTv);
{
if(0 > getsockopt(sockID,SOL_SOCKET,SO_ERROR,(void*)(&iValOpt),&iLength))
{
return -1
}
if (0 != iValOpt)
{
return -1;
}
return success;
}
else
{
return -1;
}
}
else
{
return -1;
}
}
return success;
}
Based on your information:
You are trying to do a connect() to 54.x.x.x
The socket is non-blocking
Connection timeout is 60 sec
First, if you look into your /usr/include/asm-generic/errno.h you'll see the following:
#define EINPROGRESS 115 /* Operation now in progress */
It means an existing operation on the socket is in progress. Since, you said you are doing a connect() call, lets do a man connect:
EINPROGRESS
The socket is nonblocking and the connection cannot be completed
immediately. It is possible to select(2) or poll(2) for completion by
selecting the socket for writing. After select(2) indicates
writability, use getsockopt(2) to read the SO_ERROR option at level
SOL_SOCKET to determine whether connect() completed successfully
(SO_ERROR is zero) or unsuccessfully (SO_ERROR is one of the usual
error codes listed here, explaining the reason for the failure).
So, the best guess would be that the TCP 3-way handshake (your connect() call to 54.x.x.x IP address) is taking longer than expected to complete. Since the connect() operation is already in progress, any subsequent operation on the socket is resulting into EINPROGRESS error code. As suggested in the man page, try to use select() or poll() to check if your socket is ready to use (to perform read() or write() calls).
You can pin-point what is preventing your TCP handshake to complete by capturing and analyzing the traffic to/from your own machine and 54.x.x.x. The best tool to help you with this is called WireShark. Good luck.
This seems to be the behaviour of connect():
If the connection cannot be established immediately and O_NONBLOCK is
set for the file descriptor for the socket, connect() shall fail and
set errno to [EINPROGRESS], but the connection request shall not be
aborted, and the connection shall be established asynchronously.
Subsequent calls to connect() for the same socket, before the
connection is established, shall fail and set errno to [EALREADY].

How to find the socket connection state in C?

I have a TCP connection. Server just reads data from the client. Now, if the connection is lost, the client will get an error while writing the data to the pipe (broken pipe), but the server still listens on that pipe. Is there any way I can find if the connection is UP or NOT?
You could call getsockopt just like the following:
int error = 0;
socklen_t len = sizeof (error);
int retval = getsockopt (socket_fd, SOL_SOCKET, SO_ERROR, &error, &len);
To test if the socket is up:
if (retval != 0) {
/* there was a problem getting the error code */
fprintf(stderr, "error getting socket error code: %s\n", strerror(retval));
return;
}
if (error != 0) {
/* socket has a non zero error status */
fprintf(stderr, "socket error: %s\n", strerror(error));
}
The only way to reliably detect if a socket is still connected is to periodically try to send data. Its usually more convenient to define an application level 'ping' packet that the clients ignore, but if the protocol is already specced out without such a capability you should be able to configure tcp sockets to do this by setting the SO_KEEPALIVE socket option. I've linked to the winsock documentation, but the same functionality should be available on all BSD-like socket stacks.
TCP keepalive socket option (SO_KEEPALIVE) would help in this scenario and close server socket in case of connection loss.
There is an easy way to check socket connection state via poll call. First, you need to poll socket, whether it has POLLIN event.
If socket is not closed and there is data to read then read will return more than zero.
If there is no new data on socket, then POLLIN will be set to 0 in revents
If socket is closed then POLLIN flag will be set to one and read will return 0.
Here is small code snippet:
int client_socket_1, client_socket_2;
if ((client_socket_1 = accept(listen_socket, NULL, NULL)) < 0)
{
perror("Unable to accept s1");
abort();
}
if ((client_socket_2 = accept(listen_socket, NULL, NULL)) < 0)
{
perror("Unable to accept s2");
abort();
}
pollfd pfd[]={{client_socket_1,POLLIN,0},{client_socket_2,POLLIN,0}};
char sock_buf[1024];
while (true)
{
poll(pfd,2,5);
if (pfd[0].revents & POLLIN)
{
int sock_readden = read(client_socket_1, sock_buf, sizeof(sock_buf));
if (sock_readden == 0)
break;
if (sock_readden > 0)
write(client_socket_2, sock_buf, sock_readden);
}
if (pfd[1].revents & POLLIN)
{
int sock_readden = read(client_socket_2, sock_buf, sizeof(sock_buf));
if (sock_readden == 0)
break;
if (sock_readden > 0)
write(client_socket_1, sock_buf, sock_readden);
}
}
Very simple, as pictured in the recv.
To check that you will want to read 1 byte from the socket with MSG_PEEK and MSG_DONT_WAIT. This will not dequeue data (PEEK) and the operation is nonblocking (DONT_WAIT)
while (recv(client->socket,NULL,1, MSG_PEEK | MSG_DONTWAIT) != 0) {
sleep(rand() % 2); // Sleep for a bit to avoid spam
fflush(stdin);
printf("I am alive: %d\n", socket);
}
// When the client has disconnected, this line will execute
printf("Client %d went away :(\n", client->socket);
Found the example here.
I had a similar problem. I wanted to know whether the server is connected to client or the client is connected to server. In such circumstances the return value of the recv function can come in handy. If the socket is not connected it will return 0 bytes. Thus using this I broke the loop and did not have to use any extra threads of functions. You might also use this same if experts feel this is the correct method.
get sock opt may be somewhat useful, however, another way would to have a signal handler installed for SIGPIPE. Basically whenever you the socket connection breaks, the kernel will send a SIGPIPE signal to the process and then you can do the needful. But this still does not provide the solution for knowing the status of the connection. hope this helps.
You should try to use: getpeername function.
now when the connection is down you will get in errno:
ENOTCONN - The socket is not connected.
which means for you DOWN.
else (if no other failures) there the return code will 0 --> which means UP.
resources:
man page: http://man7.org/linux/man-pages/man2/getpeername.2.html
On Windows you can query the precise state of any port on any network-adapter using:
GetExtendedTcpTable
You can filter it to only those related to your process, etc and do as you wish periodically monitoring as needed. This is "an alternative" approach.
You could also duplicate the socket handle and set up an IOCP/Overlapped i/o wait on the socket and monitor it that way as well.
#include <sys/socket.h>
#include <poll.h>
...
int client = accept(sock_fd, (struct sockaddr*)&address, (socklen_t*)&addrlen);
pollfd pfd = {client, POLLERR, 0}; // monitor errors occurring on client fd
...
while(true)
{
...
if(not check_connection(pfd, 5))
{
close(client);
close(sock[1]);
if(reconnect(HOST, PORT, reconnect_function))
printf("Reconnected.\n");
pfd = {client, POLLERR, 0};
}
...
}
...
bool check_connection(pollfd &pfd, int poll_timeout)
{
poll(&pfd, 1, poll_timeout);
return not (pfd.revents & POLLERR);
}
you can use SS_ISCONNECTED macro in getsockopt() function.
SS_ISCONNECTED is define in socketvar.h.
For BSD sockets I'd check out Beej's guide. When recv returns 0 you know the other side disconnected.
Now you might actually be asking, what is the easiest way to detect the other side disconnecting? One way of doing it is to have a thread always doing a recv. That thread will be able to instantly tell when the client disconnects.

Connection refused after some time on threaded process in tcp socket requests (c/linux)

I'm trying to make process that takes number of requests each second, on each request new thread is created. Each thread then opens socket connection to address (http port) sends HEAD requests, gets response and closes socket.
Problem I'm having comes when i put more then 3 requests per second, after some time i get error in send() part of function, i keep getting Connection Refused. If I input more requests per second i get errors earlier. If i put only 2 requests per second i don't get errors at all. I suspect that I'm running out of some resource but i can't find which.
Here is basic structure of code
//declarations
socketfd = socket(servinfo->ai_family,servinfo->ai_socktype,servinfo->ai_protocol);
arg = fcntl(socketfd, F_GETFL, NULL)) < 0);
arg |= O_NONBLOCK;
fcntl(socketfd, F_SETFL, arg)
if((conn = connect(socketfd, servinfo->ai_addr, servinfo->ai_addrlen)) < 0)
{
if(errno == EINPROGRESS)
{
do
{
tv.tv_sec = CONNECT_TIMEOUT;
tv.tv_usec = 0;
FD_ZERO(&myset);
FD_SET(socketfd, &myset);
if((res = select(socketfd+1, NULL, &myset, NULL, &tv) > 0))
{
if( (arg = fcntl(socketfd, F_GETFL, NULL)) < 0) {
perror("fcntl get 2");
}
arg &= (~O_NONBLOCK);
if( fcntl(socketfd, F_SETFL, arg) < 0) {
perror("fcntl set 2");
}
char szBuf[4096];
std::string htmlreq = "HEAD / HTTP/1.1\r\nHost:";
htmlreq += info->hostName;
htmlreq += "\r\n\r\n";
if((conn = send(socketfd,htmlreq.c_str(),htmlreq.size(),0)) == -1 && errno != EINTR)
{
perror("send");
close(socketfd);
return;
}
if((conn = recv(socketfd,szBuf,sizeof(szBuf)+1,0)) < 0 && errno != EINTR)
{
perror("recv");
close(socketfd);
return ;
}
close(socketfd);
// do stuff with data
break;
}
else
{
//timeout
break;
}
}while(1);
}
else
{
perror("connect");
close(socketfd);
return;
}
}
I removed some error checking from start, what i get as output is "Send: Connection Refused" after some time. I'd appreciate some pointers to what part could be causing problems, platform is ubuntu linux. I'd also be glad to post other parts of code if needed. Tnx in advance.
The resource you're probably running out of is on the server you're connecting to. The connection is being refused by the computer you're connecting to because it's either:
Configure to limit the number of connections per second ( based on some criteria )
Or the server you're connecting to is under too much load for some reason and can't take any more connections.
Since you always get the error on the third connection it could be that the server you're connecting to limits the number of connections on a per IP basis.
Edit1
You're trying to do a non-blocking connect? Now that I look at it closer it sounds like your problem is with the select, as in select is returning that the socket is readable before it's actually connected and then you're calling send. One of the things to watch out for on non-blocking connects is that the socket becomes both readable and writeable on error. Which means you need to check for both after select returns otherwise you may be missing whatever the actual error is and seeing the send error instead.
This is from Stevens UNP:
FD_ZERO(&rset);
FD_SET(sockfd, &rset);
wset = rset;
tval.tv_sec = nsec;
tval.tv_usec = 0;
if ( (n = Select(sockfd+1, &rset, &wset, NULL,
nsec ? &tval : NULL)) == 0) {
close(sockfd); /* timeout */
errno = ETIMEDOUT;
return(-1);
}
if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) {
len = sizeof(error);
if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
return(-1); /* Solaris pending error */
} else
err_quit("select error: sockfd not set");
done:
Fcntl(sockfd, F_SETFL, flags); /* restore file status flags */
if (error) {
close(sockfd); /* just in case */
errno = error;
return(-1);
}
return(0);
There are quite a few problems in your code.
First you set the socket to non blocking. I don't understand why you do this. The connect function has an internal timeout and so won't block.
Another problem of your code is that the first if statement will skip the instruction block if the connection immediately succeeds ! Which may happen.
You apparently want to first send the HEAD message. There is no real need to make this one non blocking unless you expect the remote server or the network to be very slow and want a time out on it. In this case the select with non blocking socket would make sens.
Once you send the HEAD message, you expect some data in response that you collect with the recv function. Be aware that this function call may return before the whole data sent is received. You need an independent way to determine that all the data sent has been received. Would the server close the connection ? This would detected by the recv function returning 0.
So the recv should be wrapped into a loop where you append to received data to some buffer or a file and quit when recv returns 0. Use a non blocking socket if you want to add a timeout on this recv operation which may indeed block.
But first try without timeouts to be sure it works at full speed without blocking as your current version.
I suspect the initial connect is slow because of name and IP adresse resolution, and gets faster in subsequent calls because data is cached.

Resources