More work on new streams

This commit is contained in:
Alex Hultman
2018-09-27 23:44:46 +02:00
parent ee81e9b0b0
commit 2c511ec904
7 changed files with 266 additions and 249 deletions
+44 -47
View File
@@ -11,6 +11,7 @@ namespace uWS {
template <bool SSL>
struct AsyncSocket : StaticDispatch<SSL> {
template <bool> friend struct HttpContext;
protected:
using SOCKET_TYPE = typename StaticDispatch<SSL>::SOCKET_TYPE;
using StaticDispatch<SSL>::static_dispatch;
@@ -23,39 +24,68 @@ protected:
}
}
public:
void *getExt() {
return static_dispatch(us_ssl_socket_ext, us_socket_ext)((SOCKET_TYPE *) this);
}
void timeout(unsigned int seconds) {
static_dispatch(us_ssl_socket_timeout, us_socket_timeout)((SOCKET_TYPE *) this, seconds);
}
void shutdown() {
static_dispatch(us_ssl_socket_shutdown, us_socket_shutdown)((SOCKET_TYPE *) this);
}
SOCKET_TYPE *close() {
return static_dispatch(us_ssl_socket_close, us_socket_close)((SOCKET_TYPE *) this);
}
/* Cork this socket. Only one socket may ever be corked per-loop at any given time */
void cork() {
std::cout << "Cork called" << std::endl;
LoopData *loopData = getLoopData();
loopData->corked = true;
}
/* Write in three levels of prioritization: cork-buffer, syscall, socket-buffer */
/* Write in three levels of prioritization: cork-buffer, syscall, socket-buffer. Always drain if possible. */
// todo: consider supporting nextLength = UNKNOWN as -1 (more but unknown size)
int write(const char *src, int length, bool optionally = false, int nextLength = 0) {
LoopData *loopData = getLoopData();
//std::cout << "Write called with length: " << length << ", optionally: " << optionally << std::endl;
std::cout << "Write called with length: " << length << ", optionally: " << optionally << std::endl;
AsyncSocketData<SSL> *asyncSocketData = (AsyncSocketData<SSL> *) getExt();
/* Do nothing for a null sized chunk */
if (length == 0) {
if (length == 0 && !asyncSocketData->buffer.length()) {
//std::cout << "Write returned: 0" << std::endl;
return 0;
}
AsyncSocketData<SSL> *asyncSocketData = (AsyncSocketData<SSL> *) getExt();
/* Do not write anything if we have a per-socket buffer */
if (asyncSocketData->buffer.length()) {
if (optionally) {
//std::cout << "Write returned: 0" << std::endl;
// we have buffer and we are optionally, if drain then drain else quit
// drain here
std::cout << "Drain path" << std::endl;
// will just end up in a loop!
int written = static_dispatch(us_ssl_socket_write, us_socket_write)((SOCKET_TYPE *) this, asyncSocketData->buffer.data(), asyncSocketData->buffer.length(), nextLength != 0);//write(asyncSocketData->buffer.data(), asyncSocketData->buffer.length(), optionally, 0, true);
// removeBuffer
asyncSocketData->buffer = asyncSocketData->buffer.substr(written);
// should we really return this here? should be 0 as we took 0 new data!
return 0;
} else {
std::cout << "Buffering at top of write!" << std::endl;
std::cout << "Buffering at top of write (really bad)!" << std::endl;
/* At least we can reserve room for next chunk if we know it up front */
if (nextLength) {
@@ -104,7 +134,7 @@ public:
return written;
}
std::cout << "Buffering at bottom of write!" << std::endl;
std::cout << "Buffering at bottom of write (okay)!" << std::endl;
/* Fall back to worst possible case (should be very rare for HTTP) */
/* At least we can reserve room for next chunk if we know it up front */
@@ -124,6 +154,9 @@ public:
/* Uncork this socket and flush or buffer any corked and/or passed data. It is essential to remember doing this. */
/* It does NOT count bytes written from cork buffer (they are already accounted for in the write call responsible for its corking)! */
int uncork(const char *src = nullptr, int length = 0, bool optionally = false) {
std::cout << "Uncork called with length: " << length << std::endl;
LoopData *loopData = getLoopData();
if (loopData->corked) {
@@ -137,48 +170,12 @@ public:
/* We should only return with new writes, not things written to cork already */
return write(src, length, optionally, 0);
} else {
std::cout << "Not even corked!" << std::endl;
}
return 0;
}
/* Check if this socket has buffered data */
bool hasBuffer() {
return ((AsyncSocketData<SSL> *) getExt())->buffer.length() > 0;
}
/* Drain any socket-buffer while also optionally sending a chunk */
int mergeDrain(std::string_view optionalChunk = {}) {
// strategy: if we have two parts and both will fit in cork buffer then cork them and recursively send them off
// write any per-socket buffer and optionally more
AsyncSocketData<SSL> *asyncSocketData = (AsyncSocketData<SSL> *) getExt();
// not handled yet
if (asyncSocketData->buffer.length()) {
std::cout << "ERROR! has socket buffer!" << std::endl;
exit(0);
}
/* Write the optional part */
return write(optionalChunk.data(), optionalChunk.length(), true, 0);
}
/* These should not be public to the user! */
void timeout(unsigned int seconds) {
static_dispatch(us_ssl_socket_timeout, us_socket_timeout)((SOCKET_TYPE *) this, seconds);
}
void shutdown() {
static_dispatch(us_ssl_socket_shutdown, us_socket_shutdown)((SOCKET_TYPE *) this);
}
SOCKET_TYPE *close() {
return static_dispatch(us_ssl_socket_close, us_socket_close)((SOCKET_TYPE *) this);
}
};
}