OpenSSL Blocking Sockets SSL_read blocks [closed] - sockets

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I am using blocking sockets in OpenSSL connection. SSL_read blocks sometimes for few seconds. In server - BIO_write is used to send data in variable buffer size. In client - first SSL_read to get buffer size succeeds but following SSL_read to get buffer data blocks for few seconds(this issue is simulated after 2 to 3mins) even though data sent successfully. I wait on poll() to invoke client read function. How to correct these problem in blocking sockets?
Server Code
void process_and_send() {
// sending variable size buffer each time
// sbuf - first 4 bytes contains sbuf size information
send_data(sbuf, sbufSize);
}
void send_data(void *sbuf, int pending_len) {
while(pending_len > 0) {
result = BIO_write(bio, sbuf, pending_len);
if(result == 0) {
attempts = 0;
LOG_D("%s", log_str(SSL_CONN_CLOSE));
SSL_FN_TRACE("connection closed\n");
break;
}
else if(result < 0) {
LOG_I("%s", log_str(SSL_WRITE_FAIL));
SSL_FN_TRACE("BIO_write fail\n");
if(errno == EINTR) {
continue;
}
if(errno == EAGAIN) {
attempts++;
continue;
}
if(errno == EWOULDBLOCK) {
attempts++;
continue;
}
break;
}
else {
BIO_flush(bio);
pending_len -= result;
sbuf += result;
}
}
}
Client Code
// wait on poll() and call receive_and_process
void receive_and_process() {
int rbufSize = 0;
// get the size of data to read
receive_data((void *)&rbufSize, sizeof(Int));
// this call blocks for few seconds
receive_data(rbuf, rbufSize);
}
void receive_data(void *rbuf, int pending_len) {
while(pending_len > 0) {
result = SSL_read(ssl, rbuf, pending_len);
if(result == 0) {
LOG_D("%s", log_str(SSL_CONN_CLOSE));
SSL_FN_TRACE("connection closed\n");
return NULL;
}
else if(result < 0) {
if(errno == ETIMEDOUT) {
SSL_FN_ERROR("SSL read timeout: \n");
continue;
}
if(errno == EINTR) {
continue;
}
if(errno == EAGAIN) {
continue;
}
if(errno == EWOULDBLOCK) {
continue;
}
SSL_FN_ERROR("SSL read fail error no: %s\n",
ERR_reason_error_string(ERR_get_error()));
LOG_I("%s", log_str(SSL_READ_FAIL));
return NULL;
}
pending_len -= result;
rbuf += result;
FN_ERROR("after read full data pending len %d\n", pending_len);
}
}

Well, for starters, your client code can't compile as shown, because receive_data() has a void return type, so return NULL is a compiler error. Also, you can't use the += operator on a void* pointer, that is also a compiler error.
Beside that, if SSL_read() returns < 0, you need to use SSL_get_error() instead of errno to find out why it failed. Don't use errno unless SSL_get_error() returns SSL_ERROR_SYSCALL. If SSL_get_error() returns SSL_ERROR_SSL, use ERR_get_error() and related functions instead. And, make sure you are handling the SSL_ERROR_WANT_READ and SSL_ERROR_WANT_WRITE errors.
Also, when sending multi-byte integers, you have to deal with endian issues if you are sending across machine boundaries. Best to use functions like htonl() and ntohl() to send integers over the connection in network byte order.
Try something more like this:
Server:
void process_and_send() {
// sending variable size buffer each time
// sbuf - DO NOT store the size information in the first 4 bytes!
// handle the size separately...
int32_t size = htonl(sbufSize);
if (send_data(&size, sizeof(size)))
send_data(sbuf, sbufSize);
}
bool send_data(void *sbuf, int pending_len) {
unsigned char *pbuf = (unsigned char *) sbuf;
while (pending_len > 0) {
result = BIO_write(bio, pbuf, pending_len);
if (result > 0) {
BIO_flush(bio);
pbuf += result;
pending_len -= result;
}
else if (result == 0) {
attempts = 0;
LOG_D("%s", log_str(SSL_CONN_CLOSE));
SSL_FN_TRACE("connection closed\n");
return false;
}
else if (!BIO_should_retry(bio)) {
LOG_I("%s", log_str(SSL_WRITE_FAIL));
SSL_FN_TRACE("BIO_write fail\n");
return false;
}
else {
++attempts;
}
}
return true;
}
Client:
// wait on poll() and call receive_and_process
void receive_and_process() {
int32_t rbufSize = 0;
// get the size of data to read
if (receive_data(&rbufSize, sizeof(rbufSize))) {
rbufSize = ntohl(rbufSize);
// TODO: make sure rbuf is at least rbufSize in size...
receive_data(rbuf, rbufSize);
}
}
bool receive_data(void *rbuf, int pending_len) {
unsigned char *pbuf = (unsigned char *) rbuf;
while (pending_len > 0) {
result = SSL_read(ssl, pbuf, pending_len);
if (result > 0) {
pbuf += result;
pending_len -= result;
FN_ERROR("after read full data pending len %d\n", pending_len);
}
else {
result = SSL_get_error();
if (result == SSL_ERROR_ZERO_RETURN) {
LOG_D("%s", log_str(SSL_CONN_CLOSE));
SSL_FN_TRACE("connection closed\n");
}
else {
if (result == SSL_ERROR_WANT_READ) {
// TODO: use select() to wait for the socket to be readable before trying again...
continue;
}
else if (result == SSL_ERROR_WANT_WRITE) {
// TODO: use select() to wait for the socket to be writable before trying again...
continue;
}
else if (result == SSL_ERROR_SYSCALL) {
if ((errno == EINTR) || (errno == EAGAIN) || (errno == EWOULDBLOCK)) {
continue;
}
if (errno == ETIMEDOUT) {
SSL_FN_ERROR("SSL read timeout: \n");
continue;
}
SSL_FN_ERROR("SSL read fail error no: %d\n", errno);
}
else if (result == SSL_ERROR_SSL) {
SSL_FN_ERROR("SSL read fail error no: %s\n",
ERR_reason_error_string(ERR_get_error()));
}
else {
SSL_FN_ERROR("SSL read fail error no: %d\n", result);
}
LOG_I("%s", log_str(SSL_READ_FAIL));
}
return false;
}
}
return true;
}

Related

How to send data greatter than 512 bytes using flutter_blue?

I have a file that is larger than 512 bytes to send to an esp32. I'm sending "withoutResponse: false", the flutter_blue library does the split according to the mtu size without problems, but when it reaches 512 bytes it returns an error to write in characteristic. To solve this I have a function that splits the file and writes each 512 bytes.
Esp32 can send me files larger than 512 without doing anything. Can I send larger files without splitting?
Example of code or library that makes this possible
ok, I decided to switch to the flutter_reactive_ble library, and I developed code similar to this one. Basically I split the file into smaller packets of 4096 bytes (this was defined in my communication protocol with esp32), then I call the function that sends and it splits again the file into packets the size of mtu less 19 bytes that are from the header. In the last packet I "writeWithResponse" and wait for the response, if it responds ok, increment and send the next package and repit the processs until the end of file.
late StreamSubscription<List<int>>? subscribeStream;
List<int> bytesOfFile = [];
int _size = 0;
int _increment = 0;
List<int> _returnOfSubscribe = [];
int _indexOfUploadController = 0;
Future<void> subscribeCharacteristic() async {
subscribeStream = widget
.subscribeToCharacteristic(widget.rcharacteristic)
.listen((event) {
debugPrint("resposta${hexToString(event)}");
setState(() {
_returnOfSubscribe = event;
if (_returnOfSubscribe != 'code of confirm reception file') {
debugPrint('err');
} else {
_increment++;
actualize();
}
});
});
}
void actualize() async {
int splitSize = 4096;
Iterable<int> s;
int n = (bytesOfFile.length / splitSize).ceil();
//if is the last split
if (_increment >= n) {
if (_returnOfSubscribe == 'code of confirm end of file') {
debugPrint("success");
} else {
debugPrint("err");
}
return;
}
if ((_size + splitSize) < bytesOfFile.length) {
s = bytesOfFile.getRange(_size, _size + splitSize);
} else {
s = bytesOfFile.getRange(_size, bytesOfFile.length);
}
await writeLongData(s.toList());
_size += splitSize;
}
writeLongData(List<int> data) async {
int splitSize = mtuNotifier.value - 19;
Iterable<int> s;
int size = 0;
int n = (data.length / splitSize).ceil();
for (int i = 0; i < n; i++) {
if ((size + splitSize) < data.length) {
s = data.getRange(size, size + splitSize);
} else {
s = data.getRange(size, data.length);
}
try {
if ((size + splitSize) < data.length) {
await widget.writeWithoutResponse(widget.wcharacteristic, s.toList());
} else {
//if the last, write with response
await widget.writeWithResponse(widget.wcharacteristic, s.toList());
}
} catch (e) {
debugPrint('$e');
return;
}
size += splitSize;
}
}

recv function in socket programming fails when I am using MSG_WAITALL flag

I have written a very simple code for client side of a socket.
this is my receive function:
int n32RecvLength = 10;
do {
n32RecvLength = recv(m_socketConnectSocket, m_szRecvBuffer, m_n32BufferLength, MSG_WAITALL);
if ( n32RecvLength > 0 )
{
printf("\nBytes received: %d\n", n32RecvLength);
//for(int i = 0; i< n32RecvLength; i++)
//putchar(m_szRecvBuffer[i]);
if (evRecPacket != NULL)
{
evRecPacket(static_cast<void*>(m_ptrvDerivedClass),reinterpret_cast<unsigned char*>(m_szRecvBuffer) , n32RecvLength);
}
}
else if ( n32RecvLength == 0 )
{
printf("Connection closed!!!!!!!\n");
if(evDisconnected != NULL)
evDisconnected(static_cast<void*>(m_ptrvDerivedClass));
break;
}
else
{
int errorNum = WSAGetLastError();
if (errorNum == WSAETIMEDOUT)
{
printf ("\n timeOut\n");
n32RecvLength = 1;
}
else
{
printf("recv failed with error: %d\n", errorNum);
if(evDisconnected != NULL)
evDisconnected(static_cast<void*>(m_ptrvDerivedClass));
break;
}
}
} while( n32RecvLength > 0 );
and I have initialized it in this function:
WSADATA swsaData;
struct addrinfo *result = NULL;
struct addrinfo hints;
unsigned int n32CheckCondition = 0;
n32CheckCondition = WSAStartup(MAKEWORD(2,2), &swsaData);
if (n32CheckCondition != 0) {
printf("WSAStartup failed with error: %d\n", n32CheckCondition);
return;
}
ZeroMemory( &hints, sizeof(hints) );
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
char szPortNumber[100];
itoa(m_n32PortNumber,szPortNumber , 10);
n32CheckCondition = getaddrinfo(m_szIpServerAddr, szPortNumber, &hints, & m_ptrsResult);
if ( n32CheckCondition != 0 ) {
printf("getaddrinfo failed with error: %d\n", n32CheckCondition);
WSACleanup();
return;
}
m_socketConnectSocket = socket( m_ptrsResult->ai_family, m_ptrsResult->ai_socktype, m_ptrsResult->ai_protocol);
if (m_socketConnectSocket == INVALID_SOCKET)
{
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return;
}
// to set timeout feature to your system, uncomment the two following lines and adjust it
DWORD timeout = 10000; // mili second!
setsockopt(m_socketConnectSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));
I am using recv function with MSG_WAITALL flag. I have set the timeout = 10000 milliseconds.
I have set the m_n32BufferLength = 8. when I send a 8-byte data, it works fine, but when I send 9 byte it shows first 8 bytes and after a few second (timeout value) the recv(...) returns zero. I know when recv returns zero, it means that socket has been closed. but I have not closed the socket. and I also loss the 9th byte of my data.
could you please tell me what I should do?

IOCP not getting triggered

I have writen an IOCP program and I am testing it through VPN.
It was all working OK, but then the server disconnected and the client GetQueuedCompletionStatus didn't trigger an exception.
I waited for one day,cbut it didn't get better. When I changed to a new VPN, the problem was solved, and I didn't get that problem later.
What's wrong? Has anybody seen the same problem before?
enter code here
enter code here
#include "XYTransport.h"
//---------------------------------------------------------------------------
#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
//---------------------------------------------------------------------------
#define XYTCP_LIST_CLIENT0 0
#define XYTCP_LIST_CLIENT1 1
//---------------------------------------------------------------------------
#define XYTRANSPORT_TYPE_TCP_OPEN 0
#define XYTRANSPORT_TYPE_TCP_RECV 1
#define XYTRANSPORT_TYPE_TCP_SEND 2
//---------------------------------------------------------------------------
typedef struct tagXYOVERLAPPED
{
OVERLAPPED o;
SOCKET s;
UINT flags;
WSABUF wb;
}XYOVERLAPPED, *PXYOVERLAPPED;
//---------------------------------------------------------------------------
inline LPVOID XYAlloc(HANDLE heap, UINT size)
{
return(HeapAlloc(heap, 0, size));
}
inline VOID XYFree(HANDLE heap, LPVOID lpdata)
{
HeapFree(heap, 0, lpdata);
}
inline PXYOVERLAPPED XYOverlappedPop(PXYTRANSPORT pt, LPBYTE buffer, SOCKET s)
{
PXYOVERLAPPED pto = NULL;
SOCKADDR_IN name;
if (buffer == NULL)
{
buffer = (LPBYTE)VirtualAlloc(NULL, pt->bufferlength, MEM_COMMIT, PAGE_READWRITE);
}
if (buffer != NULL)
{
pto = (PXYOVERLAPPED)MALLOC(sizeof(XYOVERLAPPED));
if (pto != NULL)
{
pto->wb.buf = (char *)buffer;
pto->wb.len = pt->bufferlength;
if (s == INVALID_SOCKET)
{
pto->s = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
if (pto->s != INVALID_SOCKET)
{
ZeroMemory(&name, sizeof(name));
name.sin_family = AF_INET;
name.sin_addr.S_un.S_addr = INADDR_ANY;
//name.sin_port = fn_htons(0);
name.sin_port = 0;
if (bind(pto->s, (const SOCKADDR *)&name, sizeof(name)) == 0)
{
if (CreateIoCompletionPort((HANDLE)pto->s, pt->hcompletion, (ULONG_PTR)pto->s, 0) == pt->hcompletion)
{
//
}
}
}
}
else
{
pto->s = s;
}
}
}
return(pto);
}
BOOL XYTCPPushReceive(PXYTRANSPORT pt, PXYOVERLAPPED pto, SOCKET s)
{
DWORD numberofbytes;
DWORD flags = 0;
BOOL result;
int error;
if (pto == NULL)
{
pto = XYOverlappedPop(pt, NULL, s);
}
ZeroMemory(&pto->o, sizeof(OVERLAPPED));
pto->flags = XYTRANSPORT_TYPE_TCP_RECV;
result = WSARecv(pto->s, &pto->wb, 1, &numberofbytes, &flags, &pto->o, NULL) != SOCKET_ERROR;
if (!result)
{
error = WSAGetLastError();
result = error == WSA_IO_PENDING;
if (!result)
{
printf("WSARecv\n");
}
}
return(result);
}
inline BOOL XYTCPPushSend(PXYTRANSPORT pt, PXYOVERLAPPED pto)
{
DWORD numberofbytes;
ULONG flags = MSG_PARTIAL;
BOOL result;
int error;
ZeroMemory(&pto->o, sizeof(OVERLAPPED));
pto->flags = XYTRANSPORT_TYPE_TCP_SEND;
//
pto->wb.len = 1024;
//
result = WSASend(pto->s, &pto->wb, 1, &numberofbytes, flags, &pto->o, NULL) != SOCKET_ERROR;
if (!result)
{
error = WSAGetLastError();
result = error == WSA_IO_PENDING;
if (!result)
{
printf("Send Error\n");
}
}
return(result);
}
DWORD WINAPI XYTransportWorkProc(LPVOID parameter)
{
PXYTRANSPORT pt = (PXYTRANSPORT)parameter;
HANDLE hcompletion = pt->hcompletion;
LPOVERLAPPED po;
PXYOVERLAPPED pto;
ULONG_PTR completionkey;
DWORD numberofbytes;
SOCKET s;
BOOL flag;
UINT type;
UINT count;
UINT error;
while(pt->working)
{
flag = GetQueuedCompletionStatus(hcompletion, &numberofbytes, &completionkey, &po, INFINITE);
if (po != NULL)
{
pto = (PXYOVERLAPPED)CONTAINING_RECORD(po, XYOVERLAPPED, o);
s = (SOCKET)completionkey;
type = pto->flags;
if (!flag)
{
//OutputDebugValue(_T("Except Error"), type, numberofbytes);
printf("Except Error %d\n", type);
}
if (numberofbytes == 0)
{
//OutputDebugValue(_T("Length Error"), type);
printf("Length Error %d\n", type);
}
if (!flag)
{
numberofbytes = 0;
}
switch (type)
{
case XYTRANSPORT_TYPE_TCP_OPEN:
if (flag)
{
setsockopt(s, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0);
XYTCPPushSend(pt, pto);
printf("connected\n");
if (!XYTCPPushReceive(pt, NULL, s))
{
//
}
else
{
printf("post recv\n");
}
break;
}
break;
case XYTRANSPORT_TYPE_TCP_RECV:
if (numberofbytes > 0)
{
XYTCPPushReceive(pt, pto, s);
//OutputDebugString(_T("Recv"));
printf("Recv %d\n", numberofbytes);
}
else
{
printf("Recv Error\n");
}
break;
case XYTRANSPORT_TYPE_TCP_SEND:
if (numberofbytes > 0)
{
XYTCPPushSend(pt, pto);
printf("Send %d\n", numberofbytes);
}
else
{
printf("Send Except\n");
}
break;
default:
break;
}
}
else
{
printf("Quit %d, %d", GetCurrentThreadId(), flag);
break;
}
}
return(0);
}
VOID XYTransportStartup(PXYTRANSPORT pt, UINT pagesize)
{
pt->hcompletion = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1);
if (pt->hcompletion != INVALID_HANDLE_VALUE)
{
pt->lpfnConnectEx = NULL;
pt->bufferlength = pagesize;
pt->working = TRUE;
pt->hthread = CreateThread(NULL, 0, XYTransportWorkProc, (LPVOID)pt, 0, NULL);
}
}
BOOL XYTCPConnect(PXYTRANSPORT pt, const CHAR *host, USHORT port)
{
GUID id = WSAID_CONNECTEX;
DWORD numberofbytes = 0;
PXYOVERLAPPED pto;
SOCKADDR_IN name;
BOOL result = FALSE;
int error;
pto = XYOverlappedPop(pt, NULL, INVALID_SOCKET);
if (pt->lpfnConnectEx != NULL || WSAIoctl(pto->s, SIO_GET_EXTENSION_FUNCTION_POINTER, &id, sizeof(id), &pt->lpfnConnectEx, sizeof(pt->lpfnConnectEx), &numberofbytes, NULL, NULL) != SOCKET_ERROR)
{
ZeroMemory(&pto->o, sizeof(OVERLAPPED));
pto->flags = XYTRANSPORT_TYPE_TCP_OPEN;
ZeroMemory(&name, sizeof(name));
name.sin_family = AF_INET;
name.sin_port = htons(port);
name.sin_addr.S_un.S_addr = inet_addr(host);
if (name.sin_addr.S_un.S_addr != INADDR_NONE)
{
numberofbytes = 0;
result = pt->lpfnConnectEx(pto->s, (SOCKADDR *)&name, sizeof(name), NULL, 0, &numberofbytes, &pto->o);
if(!result)
{
error = WSAGetLastError();
result = error == ERROR_IO_PENDING;
if (!result)
{
printf("ConnectEx error\n");
}
}
}
}
return(result);
}
//---------------------------------------------------------------------------
the client Thrown an exception is what i desired,so i can know.
I am using C language to write. Under normal circumstances, disconnect one end and the other end will trigger an exception, but I have found that sometimes have to wait a very long time, at least I'm waiting for more than one day are not triggered, and sometimes even in the off time can continue to deliver WSASend success for some time.

STM32 atoi and strtol sometimes missing first 2 digits

I am reading a value sent over RS485 which is the value of an encoder I first check if it has returned an E character (the encoder is reporting an error) and if not then do the following
*position = atoi( buffer );
// Also tried *position = (s32) strtol(buffer,NULL,10);
The value in the buffer is 4033536 and position gets set to 33536 this does not happen every time in this function probably 1 in 1000 times maybe although I am not counting. Setting the program counter back and doing the line again if has failed returns the same result but starting the debugger again causes the value to convert correctly.
I am using keil uvision 4, its a custom board using an stm32f103vet6 and the stm32f10 library V2.0.1 This one has really got me stumped never come across something like this before any help would be much appreciated.
Thanks
As no one knows I will just post what I ended up doing which was to write my own function for convertion not ideal but it worked.
bool cdec2s32(char* text, s32 *destination)
{
s32 tempResult = 0;
char currentChar;
u8 numDigits = 0;
bool negative = FALSE;
bool warning = FALSE;
if(*text == '-')
{
negative = TRUE;
text++;
}
while(*text != 0x00 && *text != '\r') //while current character not null or carridge return
{
numDigits++;
if(*text >= '0' && *text <= '9')
{
currentChar = *text;
currentChar -= '0';
if((warning && ((currentChar > 7 && !negative) || currentChar > 8 && negative )) || numDigits > 10) // Check number not too large
{
tempResult = 2147483647;
if(negative)
tempResult *= -1;
*destination = tempResult;
return FALSE;
}
tempResult *= 10;
tempResult += currentChar;
text++;
if(numDigits >= 9)
{
if(tempResult >= 214748364)
{
warning = TRUE; //Need to check next digit as close to limit
}
}
}
else if(*text == '.' || *text == ',')
{
break;
}
else
return FALSE;
}
if(negative)
tempResult *= -1;
*destination = tempResult;
return TRUE;
}

WSAWaitForMultipleEvents returns timeout when send() is successful

I am working on a application which involves socket programming. I am trying to implement reset functionality in this application in case server is closed or crashed for any reason. For reset I need to reestablish communication between the client and server after manual restart of server. Now I am able to send request from client to server which server would process and send reply to client. Send() function at server side is returning with success but WSAWaitForMultipleEvents() function at client side is returning with WSA_TIME_OUT every time.
I restart my socket at client side with SO_REUSEADDR true value on reset. I am very new to network programming i am not able to understand why this is happening.
here is my code at client side. Its little messed up so please bear with me
void
SocketListner::run()
{
// std::cout << "Thread ID of SocketListener : " << QThread::currentThreadId() << "\n";
if(_isFrameGrabber)
{
_listenForFrames();
}
else
{
_listenForRequests();
}
}
void
SocketListner::_listenForRequests()
{
DWORD eventVal;
unsigned int eventSock;
WSANETWORKEVENTS networkEvents;
std::stringstream ss;
int bufferLength = 500;
char * msg = new char[bufferLength];
std::string Msg = "";
int retCode;
int diff;
while(!_done)
{
// Giving it one second less than the condition wait time
// OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_destructorMutex);
if((eventVal=WSAWaitForMultipleEvents(_eventCnt, _socketEvents, false, 3000, false)) == WSA_WAIT_FAILED)
{
ss.str("");
ss << "WSAWaitForMultipleEvents() failed with error : " << WSAGetLastError();
LOG_ERROR(ss.str());
emit socketErrorSignal(eventVal);
break;
}
else if(eventVal == WSA_WAIT_TIMEOUT)
{
//OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
if(_done)
{
WSACloseEvent(_socketEvents[0]);
if(_eventCnt==2)
WSACloseEvent(_socketEvents[1]);
break;
}
continue;
}
if( (diff=(eventVal - WSA_WAIT_EVENT_0)) == 0 )
eventSock = s_sock;
else if(diff == 1)
eventSock = c_sock;
else
continue;
if((WSAEnumNetworkEvents(eventSock, _socketEvents[eventVal - WSA_WAIT_EVENT_0], &networkEvents)) == SOCKET_ERROR)
{
ss.str("");
ss << "WSAEnumNetworkEvents() failed with error : " << WSAGetLastError();
LOG_ERROR(ss.str());
// break;
}
if (networkEvents.lNetworkEvents & FD_ACCEPT)
{
if (networkEvents.iErrorCode[FD_ACCEPT_BIT] != 0)
{
ss.str("");
ss << "FD_ACCEPT failed with error : " << networkEvents.iErrorCode[FD_ACCEPT_BIT];
LOG_ERROR(ss.str());
break;
}
if ((c_sock = accept(eventSock, NULL, NULL)) == INVALID_SOCKET)
{
ss.str("");
ss << "accept() failed with error : " << WSAGetLastError();
LOG_ERROR(ss.str());
break;
}
if ((_socketEvents[_eventCnt] = WSACreateEvent()) == WSA_INVALID_EVENT)
{
std::stringstream ss;
ss << "WSACreateEvent() failed with error : " << WSAGetLastError();
LOG_ERROR(ss.str());
break;
}
if( WSAEventSelect(c_sock, _socketEvents[_eventCnt], FD_READ | FD_CLOSE) == SOCKET_ERROR)
{
ss.str("");
ss << "WSAEventSelect() failed with error : " << WSAGetLastError();
LOG_ERROR(ss.str());
break;
}
++_eventCnt;
}
if(networkEvents.lNetworkEvents & FD_READ)
{
if (networkEvents.lNetworkEvents & FD_READ && networkEvents.iErrorCode[FD_READ_BIT] != 0)
{
ss.str("");
ss << "FD_READ failed with error : " << networkEvents.iErrorCode[FD_READ_BIT];
LOG_ERROR(ss.str());
}
if((retCode = recv(eventSock, msg, bufferLength, 0)) > 0)
{
int place = 0;
while(place < retCode)
{
if(msg[place] == '\n' && Msg.length() != 0)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
//Naresh: Replacing std::vector by std::queue
_requests.push(Msg);
Msg = "";
}
else
{
if(msg[place] != '\0')
Msg.push_back(msg[place]);
}
++place;
}
}
//Abhishek: Testing Complete else block
else if(retCode == 0 || WSAGetLastError() == WSAECONNRESET)
{
//Abhishek
shutdown(c_sock, SD_BOTH);
shutdown(s_sock, SD_BOTH);
closesocket(c_sock);
closesocket(s_sock);
int error = WSAGetLastError();
if(!_initialize())
{
_done = true;
return;
}
}
else if(retCode == SOCKET_ERROR)
{
bool stopListening=false;
int errorCode = WSAGetLastError();
_processSocketError(errorCode, stopListening);
if(stopListening)
{
LOG_WARNING("Connection with the partner lost.");
emit socketErrorSignal(errorCode);
break;
}
}
}
if(networkEvents.lNetworkEvents & FD_CLOSE)
{
if (networkEvents.iErrorCode[FD_CLOSE_BIT] != 0)
{
ss.str("");
ss << "FD_CLOSE failed with error : " << networkEvents.iErrorCode[FD_CLOSE_BIT];
LOG_ERROR(ss.str());
emit socketErrorSignal(networkEvents.iErrorCode[FD_CLOSE_BIT]);
}
else if(!_stopped)
{
LOG_ERROR("Lost Connection with Wall.");
emit socketErrorSignal(networkEvents.iErrorCode[FD_CLOSE_BIT]);
}
closesocket(eventSock);
break;
}
//Sleep(100);
} //While
delete[] msg;
msg = NULL;
// If any failure occurs make the _bDone variable to true, as thread is no longer running
_cleanUpCondition.signal();
}
here is _initialize function
bool
SocketListner::_initialize()
{
if(_IP.length() <= 0)
{
LOG_ERROR("Host IP Address : " + _IP + " is invalid.");
return false;
}
//Naresh: replacing vector by queue
while(!_requests.empty())
{
_requests.pop();
}
WSADATA wsaData;
if(WSAStartup(0x101,&wsaData) != 0)
{
LOG_ERROR("Failed WSAStartUp() call.");
return false;
}
sockaddr_in SockAddr;
SockAddr.sin_family = AF_INET;
SockAddr.sin_port = htons(_port);
SockAddr.sin_addr.s_addr = inet_addr(_IP.c_str());
s_sock = socket(AF_INET,SOCK_STREAM,0);
//Abhishek:BugFix for reset enable address reuse else bind() will fail
bool addrReuse = true;
setsockopt(s_sock, SOL_SOCKET, SO_REUSEADDR, (const char*) &addrReuse, sizeof(BOOL));
if(!_isFrameGrabber)
{
if ((_socketEvents[_eventCnt] = WSACreateEvent()) == WSA_INVALID_EVENT)
{
std::stringstream ss;
ss << "WSACreateEvent() failed with error : " << WSAGetLastError();
LOG_ERROR(ss.str());
return false;
}
if(WSAEventSelect(s_sock, _socketEvents[_eventCnt], FD_ACCEPT | FD_CLOSE)== SOCKET_ERROR)
{
std::stringstream ss;
ss << "WSAEventSelect() failed with error : " << WSAGetLastError();
LOG_ERROR(ss.str());
return false;
}
++_eventCnt;
}
if(s_sock == INVALID_SOCKET)
return false;
int errorCode = bind(s_sock,(sockaddr*)&SockAddr,sizeof(SockAddr));
if(errorCode == SOCKET_ERROR)
{
bool stopListening = false;
_processSocketError(WSAGetLastError(), stopListening);
return false;
}
if(listen(s_sock,10)!=0)
{
return false;
}
return true;
}
If the peer dies there won't necessarily be any events at all. The only reliable way to detect a broken connection in TCP is to write to it. The first write to a broken connection will probably succeed but a later one will fail.
I found the solution to my problem. Now I am restarting all threads and sockets on reset in my application. After that i found server was not able to send because it was not able to connect new socket. I placed a infinite loop for trying to connect to client socket in my sendData() function. Which did the trick for me.