implemented flushing for ssl connections
This commit is contained in:
parent
bc4db8d8fe
commit
872d4e9a11
|
|
@ -161,14 +161,11 @@ private:
|
|||
/**
|
||||
* Method to repeat the previous call\
|
||||
* @param monitor monitor to check if connection object still exists
|
||||
* @param result result of an earlier openssl operation
|
||||
* @param result result of an earlier SSL_get_error call
|
||||
* @return TcpState*
|
||||
*/
|
||||
TcpState *repeat(const Monitor &monitor, int result)
|
||||
TcpState *repeat(const Monitor &monitor, int error)
|
||||
{
|
||||
// error was returned, so we must investigate what is going on
|
||||
auto error = OpenSSL::SSL_get_error(_ssl, result);
|
||||
|
||||
// check the error
|
||||
switch (error) {
|
||||
case SSL_ERROR_WANT_READ:
|
||||
|
|
@ -305,7 +302,7 @@ public:
|
|||
if (result > 0) return proceed();
|
||||
|
||||
// the operation failed, we may have to repeat our call
|
||||
else return repeat(monitor, result);
|
||||
else return repeat(monitor, OpenSSL::SSL_get_error(_ssl, result));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -316,7 +313,7 @@ public:
|
|||
if (result > 0) return parse(monitor, result);
|
||||
|
||||
// the operation failed, we may have to repeat our call
|
||||
else return repeat(monitor, result);
|
||||
else return repeat(monitor, OpenSSL::SSL_get_error(_ssl, result));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -339,18 +336,35 @@ public:
|
|||
// try to send more data from the outgoing buffer
|
||||
auto result = _out.sendto(_ssl);
|
||||
|
||||
// go to the next state
|
||||
auto *state = result > 0 ? proceed() : repeat(monitor, result);
|
||||
|
||||
return state;
|
||||
|
||||
// if (result > 0) return proceed();
|
||||
//
|
||||
// // the operation failed, we may have to repeat our call
|
||||
// else return repeat(result);
|
||||
// was this a success?
|
||||
if (result > 0)
|
||||
{
|
||||
// parse the buffer
|
||||
auto *nextstate = parse(monitor, result);
|
||||
|
||||
// leap out if we move to a different state
|
||||
if (nextstate != this) return nextstate;
|
||||
}
|
||||
else
|
||||
{
|
||||
// error was returned, so we must investigate what is going on
|
||||
auto error = OpenSSL::SSL_get_error(_ssl, result);
|
||||
|
||||
// get the next state given this error
|
||||
auto *nextstate = repeat(monitor, error);
|
||||
|
||||
// leap out if we move to a different state
|
||||
if (nextstate != this) return nextstate;
|
||||
|
||||
// check the type of error, and wait now
|
||||
switch (error) {
|
||||
case SSL_ERROR_WANT_READ: wait.readable(); break;
|
||||
case SSL_ERROR_WANT_WRITE: wait.active(); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// done
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,32 @@ private:
|
|||
bool _finalized;
|
||||
|
||||
|
||||
/**
|
||||
* Report an error
|
||||
* @param monitor object to check if connection still exists
|
||||
* @return TcpState*
|
||||
*/
|
||||
TcpState *reporterror(const Monitor &monitor)
|
||||
{
|
||||
// close the socket
|
||||
close(_socket);
|
||||
|
||||
// forget the socket
|
||||
_socket = -1;
|
||||
|
||||
// if we have already told user space that connection is gone
|
||||
if (_finalized) return new TcpClosed(this);
|
||||
|
||||
// object will be finalized now
|
||||
_finalized = true;
|
||||
|
||||
// inform user space that the party is over
|
||||
_handler->onError(_connection, "ssl shutdown error");
|
||||
|
||||
// go to the final state (if not yet disconnected)
|
||||
return monitor.valid() ? new TcpClosed(this) : nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Proceed with the next operation after the previous operation was
|
||||
* a success, possibly changing the filedescriptor-monitor
|
||||
|
|
@ -96,17 +122,8 @@ private:
|
|||
return this;
|
||||
|
||||
default:
|
||||
// the shutdown failed, ignore this if user was already notified of an error
|
||||
if (_finalized) return new TcpClosed(this);
|
||||
|
||||
// object will be finalized now
|
||||
_finalized = true;
|
||||
|
||||
// inform user space that the party is over
|
||||
_handler->onError(_connection, "ssl shutdown error");
|
||||
|
||||
// go to the final state (if not yet disconnected)
|
||||
return monitor.valid() ? new TcpClosed(this) : nullptr;
|
||||
return reporterror(monitor);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -172,6 +189,42 @@ public:
|
|||
// the operation failed, we may have to repeat our call
|
||||
else return repeat(monitor, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush the connection, sent all buffered data to the socket
|
||||
* @param monitor Object to check if connection still exists
|
||||
* @return TcpState new tcp state
|
||||
*/
|
||||
virtual TcpState *flush(const Monitor &monitor) override
|
||||
{
|
||||
// create an object to wait for the filedescriptor to becomes active
|
||||
Wait wait(_socket);
|
||||
|
||||
// keep looping
|
||||
while (true)
|
||||
{
|
||||
// close the connection
|
||||
auto result = OpenSSL::SSL_shutdown(_ssl);
|
||||
|
||||
// if this is a success, we can proceed with the event loop
|
||||
if (result > 0) return proceed(monitor);
|
||||
|
||||
// error was returned, so we must investigate what is going on
|
||||
auto error = OpenSSL::SSL_get_error(_ssl, result);
|
||||
|
||||
// check the error
|
||||
switch (error) {
|
||||
|
||||
// if openssl reports that socket readability or writability is needed,
|
||||
// we wait for that until this situation is reached
|
||||
case SSL_ERROR_WANT_READ: wait.readable(); break;
|
||||
case SSL_ERROR_WANT_WRITE: wait.active(); break;
|
||||
|
||||
// something is wrong, we proceed to the next state
|
||||
default: return reporterror(monitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in New Issue