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\
|
* Method to repeat the previous call\
|
||||||
* @param monitor monitor to check if connection object still exists
|
* @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*
|
* @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
|
// check the error
|
||||||
switch (error) {
|
switch (error) {
|
||||||
case SSL_ERROR_WANT_READ:
|
case SSL_ERROR_WANT_READ:
|
||||||
|
|
@ -305,7 +302,7 @@ public:
|
||||||
if (result > 0) return proceed();
|
if (result > 0) return proceed();
|
||||||
|
|
||||||
// the operation failed, we may have to repeat our call
|
// 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
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -316,7 +313,7 @@ public:
|
||||||
if (result > 0) return parse(monitor, result);
|
if (result > 0) return parse(monitor, result);
|
||||||
|
|
||||||
// the operation failed, we may have to repeat our call
|
// 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
|
// try to send more data from the outgoing buffer
|
||||||
auto result = _out.sendto(_ssl);
|
auto result = _out.sendto(_ssl);
|
||||||
|
|
||||||
// go to the next state
|
// was this a success?
|
||||||
auto *state = result > 0 ? proceed() : repeat(monitor, result);
|
if (result > 0)
|
||||||
|
{
|
||||||
return state;
|
// parse the buffer
|
||||||
|
auto *nextstate = parse(monitor, result);
|
||||||
// if (result > 0) return proceed();
|
|
||||||
//
|
// leap out if we move to a different state
|
||||||
// // the operation failed, we may have to repeat our call
|
if (nextstate != this) return nextstate;
|
||||||
// else return repeat(result);
|
}
|
||||||
|
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;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,32 @@ private:
|
||||||
bool _finalized;
|
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
|
* Proceed with the next operation after the previous operation was
|
||||||
* a success, possibly changing the filedescriptor-monitor
|
* a success, possibly changing the filedescriptor-monitor
|
||||||
|
|
@ -96,17 +122,8 @@ private:
|
||||||
return this;
|
return this;
|
||||||
|
|
||||||
default:
|
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)
|
// 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
|
// the operation failed, we may have to repeat our call
|
||||||
else return repeat(monitor, result);
|
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