More work on new streams
This commit is contained in:
+44
-47
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user