1
0
mirror of https://github.com/stefanocasazza/ULib.git synced 2025-10-05 19:18:01 +08:00

Merge pull request #5 from stefanocasazza/master

sync
This commit is contained in:
Victor Stewart 2020-07-11 23:33:05 -04:00 committed by GitHub
commit 18af5d8e12
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 3113 additions and 1270 deletions

2
configure vendored
View File

@ -33126,7 +33126,7 @@ else
fi
if test "x$use_userver_udp" != "xno" -a "$enable_http3" = "yes" -a "$USE_LIBQUICHE" = "yes"; then
if test "x$use_userver_udp" != "xno" -a "$enable_http3" = "yes" -a "$USE_LIBQUICHE" = "yes" -a "$USE_LIBURING" = "yes"; then
if true; then
HTTP3_TRUE=
HTTP3_FALSE='#'

View File

@ -2558,7 +2558,7 @@ fi
AM_CONDITIONAL(HTTP3, false)
AM_CONDITIONAL(USERVER_UDP, false)
if test "x$use_userver_udp" != "xno" -a "$enable_http3" = "yes" -a "$USE_LIBQUICHE" = "yes"; then
if test "x$use_userver_udp" != "xno" -a "$enable_http3" = "yes" -a "$USE_LIBQUICHE" = "yes" -a "$USE_LIBURING" = "yes"; then
AM_CONDITIONAL(HTTP3, true)
AM_CONDITIONAL(USERVER_UDP, true)
AC_DEFINE(USERVER_UDP, 1, [Define if use userver_udp])

View File

@ -592,10 +592,12 @@ static void setSessionPolicy()
}
else
{
U_LOGGER("*** AP:id:%v NOT FOUND ***", ap_label->rep);
ap_consume = true;
ap_notify = 0; // notify
(void) rc->hmset(U_CONSTANT_TO_PARAM("AP:id:%v consume 1 notify 3"), ap_label->rep);
// (void) rc->hmset(U_CONSTANT_TO_PARAM("AP:id:%v consume 1 notify 3"), ap_label->rep);
}
U_INTERNAL_DUMP("ap_consume = %b ap_notify = %u", ap_consume, ap_notify)

View File

@ -192,45 +192,6 @@ public:
bool connect(const char* host = U_NULLPTR, unsigned int _port = 6379);
// by Victor Stewart
UString single(const UString& pipeline)
{
U_TRACE(0, "UREDISClient_Base::single(%V)", pipeline.rep)
(void) processRequest(U_RC_MULTIBULK, U_STRING_TO_PARAM(pipeline));
return vitem[0];
}
bool silencedSingle(UString& pipeline)
{
U_TRACE(0, "UREDISClient_Base::silencedSingle(%V)", pipeline.rep)
return sendRequest(U_CONSTANT_TO_PARAM("CLIENT REPLY SKIP \r\n"), pipeline);
}
const UVector<UString>& multi(const UString& pipeline)
{
U_TRACE(0, "UREDISClient_Base::multi(%V)", pipeline.rep)
(void) processRequest(U_RC_MULTIBULK, U_STRING_TO_PARAM(pipeline));
return vitem;
}
bool silencedMulti(UString& pipeline)
{
U_TRACE(0, "UREDISClient_Base::silencedMulti(%V)", pipeline.rep)
bool result = sendRequest(U_CONSTANT_TO_PARAM("CLIENT REPLY OFF \r\n"), pipeline + "CLIENT REPLY ON \r\n");
// CLIENT REPLY ON responds with "+OK\r\n" and no way to silence it
UClient_Base::readResponse();
return result;
}
// STRING (@see http://redis.io/commands#string)
bool get(const char* key, uint32_t keylen) // Get the value of a key
@ -807,7 +768,7 @@ protected:
void init();
static void parseResponse(UString& response, UVector<UString>& parsed, size_t index, size_t terminalIndex)
static void parseResponse(UString& response, UVector<UString>& parsed, size_t index, size_t terminalIndex, ssize_t depth = 0)
{
U_TRACE(0, "UREDISClient_Base::parseResponse(index = %lu, terminalIndex = %lu)", index, terminalIndex);
@ -815,9 +776,12 @@ protected:
ptr1 = (ptr2 = response.c_pointer(index));
while (ptr2 < pend)
while (ptr2 < pend && depth > 0)
{
while (*ptr2 != '\r') ++ptr2;
while (*ptr2 != '\r')
{
++ptr2;
}
switch (*ptr1++)
{
@ -838,6 +802,7 @@ protected:
else
{
size_t length = u_strtoul(ptr1, ptr2);
parsed.push_back(response.substr((ptr2 += U_CONSTANT_SIZE(U_CRLF)), length));
ptr2 += length;
}
@ -846,15 +811,17 @@ protected:
}
// *2\r\n$10\r\n1439822796\r\n$6\r\n311090\r\n
case U_RC_MULTIBULK:
// never
default:
break;
{
depth += u_strtoul(ptr1, ptr2);
break;
}
default: break; // never
}
--depth;
ptr1 = (ptr2 += U_CONSTANT_SIZE(U_CRLF));
}
//U_DUMP_CONTAINER(parsed);
}
void processResponse()
@ -865,19 +832,13 @@ protected:
bool processRequest(char recvtype);
#if defined(U_STDCPP_ENABLE) && defined(HAVE_CXX20) && defined(U_LINUX) && !defined(__clang__) && GCC_VERSION_NUM < 100100
bool sendRequest(UStringType&& pipeline)
#else
bool sendRequest(const UString& pipeline)
#endif
{
U_TRACE_NO_PARAM(0, "UREDISClient_Base::sendRequest()");
UClient_Base::iov[0].iov_base = (caddr_t)pipeline.data();
UClient_Base::iov[0].iov_len = pipeline.size();
UClient_Base::iov[1].iov_base = (caddr_t)U_CRLF;
UClient_Base::iov[1].iov_len =
UClient_Base::iovcnt = 2;
UClient_Base::iovcnt = 1;
return UClient_Base::sendRequest(false);
}
@ -1037,7 +998,40 @@ private:
// by Victor Stewart
#if defined(U_STDCPP_ENABLE) && defined(HAVE_CXX20) && defined(U_LINUX) && !defined(__clang__) && GCC_VERSION_NUM < 100100
#if defined(U_STDCPP_ENABLE) && defined(HAVE_CXX20) && defined(U_LINUX) && !defined(__clang__)
enum class RedisOptions : uint8_t {
one = 0b0000'0001, // return one item, of type const UString&
many = 0b0000'0010, // return all items, of type const UVector<UString>&
// for cluster mode these are "psuedo-silenced", aka we wait on responses to ensure no cluster errors, but don't waste resources processing the responses
silenced = 0b0000'0100, // void
reorderable = 0b0000'1000, // only in cluster mode
copy = 0b0001'0000, // if data needs to persist through subsequent Redis calls, at the cost of copy operation
asynchronous = 0b0010'0000
};
constexpr RedisOptions operator |(RedisOptions lhs, RedisOptions rhs)
{
using underlying = typename std::underlying_type<RedisOptions>::type;
return static_cast<RedisOptions>
(
static_cast<underlying>(lhs) |
static_cast<underlying>(rhs)
);
}
constexpr bool operator &(RedisOptions lhs, RedisOptions rhs)
{
using underlying = typename std::underlying_type<RedisOptions>::type;
return static_cast<bool>
(
static_cast<underlying>(lhs) &
static_cast<underlying>(rhs)
);
}
class UCompileTimeRESPEncoder : public UCompileTimeStringFormatter {
private:
@ -1179,39 +1173,231 @@ public:
}
};
enum class RedisOptions : uint8_t {
class RedisSubscriber : public UEventFd {
private:
UString subscriptionString;
USocket *subscriptionSocket;
UHashMap<void*>* pchannelCallbackMap;
public:
virtual int handlerRead() U_DECL_FINAL;
void subscribe(const UString& channel, vPFcscs callback)
{
subscriptionString.setEmpty();
UCompileTimeRESPEncoder::encode<"SUBSCRIBE {}"_ctv>(subscriptionString, channel);
USocketExt::write(subscriptionSocket, U_STRING_TO_PARAM(subscriptionString), 500);
UString channelCopy(U_STRING_TO_PARAM(channel));
pchannelCallbackMap->insert(channelCopy, (const void*)callback);
}
void unsubscribe(const UString& channel)
{
subscriptionString.setEmpty();
UCompileTimeRESPEncoder::encode<"UNSUBSCRIBE {}"_ctv>(subscriptionString, channel);
USocketExt::write(subscriptionSocket, U_STRING_TO_PARAM(subscriptionString), 500);
(void)pchannelCallbackMap->erase(channel);
}
void connectForSubscriptions(const UString& host, uint16_t port)
{
subscriptionSocket->connectServer(host, port, 500);
U_NEW(UHashMap<void*>, pchannelCallbackMap, UHashMap<void*>());
this->UEventFd::fd = subscriptionSocket->getFd();
this->UEventFd::op_mask |= EPOLLET;
UServer_Base::addHandlerEvent(this);
}
RedisSubscriber()
{
U_NEW(USocket, subscriptionSocket, USocket);
}
one = 0b0000'0001, // const UString&
many = 0b0000'0010, // const UVector<UString>&
//these are "psuedo-silenced", aka we wait on responses to ensure no cluster errors, but don't waste resources processing the responses
silenced = 0b0000'0100, // void
reorderable = 0b0000'1000,
copy = 0b0001'0000 // if data needs to persist through subsequent Redis calls, at the cost of copy operation
~RedisSubscriber()
{
U_DELETE(subscriptionSocket);
if (pchannelCallbackMap) U_DELETE(pchannelCallbackMap);
}
};
constexpr RedisOptions operator |(RedisOptions lhs, RedisOptions rhs)
{
using underlying = typename std::underlying_type<RedisOptions>::type;
return static_cast<RedisOptions>
(
static_cast<underlying>(lhs) |
static_cast<underlying>(rhs)
);
}
class URedisClient2 : public UEventFd {
private:
constexpr bool operator &(RedisOptions lhs, RedisOptions rhs)
{
using underlying = typename std::underlying_type<RedisOptions>::type;
return static_cast<bool>
(
static_cast<underlying>(lhs) &
static_cast<underlying>(rhs)
);
}
RedisSubscriber subscriber;
USocket *socket;
static uint16_t hashslotForKey(UStringType&& hashableKey)
UString workingString;
UVector<UString> vitem;
uint8_t pendingSilencedWrites;
virtual int handlerRead() U_DECL_FINAL
{
// currently if you want to read responses asynchronsouly, you must do so by explicitly calling read() before your USP returns, otherwise the response was assumed to have been silenced, and thus we read until empty then discard.
workingString.setEmpty();
USocketExt::read(socket, workingString, U_SINGLE_READ, 100);
// every silenced response is +OK/r/n and we assume we only receive whole responses.. aka not chopped in the middle into differing TCP packets.
// thus each response is 5 bytes
pendingSilencedWrites -= (workingString.size() / 5);
return U_NOTIFIER_OK;
}
public:
// only explicitly call this to read asynchronously
template<RedisOptions options>
const decltype(auto) read(size_t commandCount)
{
vitem.clear();
workingString.setEmpty();
const char *pointer1, *pointer2, *pend;
pointer1 = pointer2 = pend = workingString.data();
auto readAndRevalidatePointers = [&] (void) -> void {
size_t index1 = pointer1 - workingString.data();
size_t index2 = pointer2 - workingString.data();
USocketExt::read(socket, workingString, U_SINGLE_READ, 500);
pointer1 = workingString.c_pointer(index1);
pointer2 = workingString.c_pointer(index2);
pend = workingString.pend();
};
uint8_t depth = commandCount;
do
{
if (pointer1 >= pend) readAndRevalidatePointers();
while (*pointer2 != '\r')
{
// no knowing where the TCP packets might have been sliced
if (UNLIKELY(++pointer2 == pend)) readAndRevalidatePointers();
}
switch (*pointer1++)
{
// :0\r\n
case U_RC_INT:
// +OK\r\n
case U_RC_INLINE:
// -Error message\r\n
case U_RC_ERROR: // only errors here are your fault
{
if (LIKELY(pendingSilencedWrites == 0)) vitem.push_back(workingString.substr(pointer1, pointer2 - pointer1));
else
{
depth++; // to counterbalance the decrement after the switch
pendingSilencedWrites--;
}
break;
}
// $-1\r\n
// $15\r\nmy-value-tester\r\n
case U_RC_BULK:
{
if (pointer1[0] == '-') vitem.push_back(UString::getStringNull());
else
{
size_t length = u_strtoul(pointer1, pointer2);
if ((pointer2 + U_CONSTANT_SIZE(U_CRLF) + length + U_CONSTANT_SIZE(U_CRLF)) > pend) readAndRevalidatePointers();
vitem.push_back(workingString.substr((pointer2 += U_CONSTANT_SIZE(U_CRLF)), length));
pointer2 += length;
}
break;
}
// *2\r\n$10\r\n1439822796\r\n$6\r\n311090\r\n
case U_RC_MULTIBULK:
{
depth += u_strtoul(pointer1, pointer2);
break;
}
default: break;
}
--depth;
pointer1 = (pointer2 += U_CONSTANT_SIZE(U_CRLF));
} while (depth > 0);
if constexpr (options & RedisOptions::one)
{
if (vitem.size())
{
if constexpr (options & RedisOptions::copy) return vitem[0].copy();
else return vitem[0];
}
else return UString::getStringNull().copy();
}
else if constexpr (options & RedisOptions::many)
{
if constexpr (options & RedisOptions::copy) return UVector<UString>(vitem);
else return (vitem);
}
}
// single refers to the targeting of a single Redis node (versus multi as in multiple nodes in a Cluster config)
template<RedisOptions options, UStringType A>
const decltype(auto) single(A&& pipeline, ssize_t commandCount = -1)
{
// this guarantees that no matter how many commands were pipelined, the only response will be +OK/r/n
// which decomplicates scenarios where you push multiple silenced writes, then issue a read where we
// would have to read out those silenced replies first before getting to the read in question.
if constexpr (options & RedisOptions::silenced)
{
pendingSilencedWrites++;
pipeline.insert(0, UCompileTimeRESPEncoder::CLIENTREPLYOFF);
pipeline.append(UCompileTimeRESPEncoder::CLIENTREPLYON);
}
USocketExt::write(socket, U_STRING_TO_PARAM(pipeline), 500);
if constexpr (options & RedisOptions::asynchronous || options & RedisOptions::silenced) return commandCount;
else return read<options>(commandCount);
}
template <auto format, RedisOptions options, typename... Ts>
const decltype(auto) single(Ts&&... ts)
{
return single<options>(workingString, UCompileTimeRESPEncoder::encode<format>(workingString, std::forward<Ts>(ts)...));
}
void subscribe(const UString& channel, vPFcscs callback) { subscriber.subscribe(channel, callback); }
void unsubscribe(const UString& channel) { subscriber.unsubscribe(channel); }
URedisClient2(const UString& host, uint16_t port)
{
U_NEW(USocket, socket, USocket);
socket->connectServer(host, port, 500);
subscriber.connectForSubscriptions(host, port);
}
~URedisClient2()
{
U_DELETE(socket);
}
};
///// CLUSTER /////
static uint16_t hashslotForKey(UStringType auto&& hashableKey)
{
return u_crc16(U_STRING_TO_PARAM(hashableKey)) % 16384;
}
@ -1238,9 +1424,10 @@ public:
pipeline.setEmpty();
}
void setHashslot(UStringType&& hashableKey)
template <UStringType T>
void setHashslot(T&& hashableKey)
{
hashslot = hashslotForKey(std::forward<UStringType>(hashableKey));
hashslot = hashslotForKey(std::forward<T>(hashableKey));
}
void append(const UString& command, uint8_t count)
@ -1329,7 +1516,7 @@ public:
RedisClusterMultiPipeline() : pipeline(300U) {}
};
class U_EXPORT UREDISClusterMaster : public UEventFd {
class U_EXPORT UREDISClusterMaster : public RedisSubscriber {
private:
struct RedisClusterNode {
@ -1345,7 +1532,7 @@ private:
RedisClusterNode(const UString& _ipAddress, uint16_t _port, uint16_t _lowHashSlot, uint16_t _highHashSlot) : ipAddress(_ipAddress), port(_port), lowHashSlot(_lowHashSlot), highHashSlot(_highHashSlot)
{
U_NEW(USocket, socket, USocket);
socket->connectServer(ipAddress, port, 1000);
socket->connectServer(ipAddress, port, 500);
}
#if defined(DEBUG)
@ -1355,17 +1542,13 @@ private:
friend class RedisClusterMultiPipeline;
UString workingString, subscriptionString;
UString workingString;
UVector<UString> parsed;
USocket *subscriptionSocket;
USocket *managementSocket;
UHashMap<RedisClusterNode *> *clusterNodes;
// speed at the cost of memory, worth it
std::unordered_map<uint16_t, USocket*> hashslotToSocket;
UHashMap<void*>* pchannelCallbackMap;
virtual int handlerRead() U_DECL_FINAL;
template <UStringType A>
USocket* socketForHashableKey(A&& hashableKey) const { return hashslotToSocket[hashslotForKey(std::forward<A>(hashableKey))]; }
@ -1388,7 +1571,7 @@ private:
size_t index1 = pointer1 - workingString.data();
size_t index2 = pointer2 - workingString.data();
USocketExt::read(socket, workingString, U_SINGLE_READ, 1000);
USocketExt::read(socket, workingString, U_SINGLE_READ, 500);
pointer1 = workingString.c_pointer(index1);
pointer2 = workingString.c_pointer(index2);
pend = workingString.pend();
@ -1482,12 +1665,12 @@ private:
} while (depth > 0);
report.end = pointer2 - workingString.data();;
report.end = pointer2 - workingString.data();
return report;
}
bool handleErrors(RedisReadReport& report, uint16_t hashslot, UStringType&& pipeline, size_t commandCount, bool skipRecloning = false)
bool handleErrors(RedisReadReport& report, uint16_t hashslot, UStringType auto&& pipeline, size_t commandCount, bool skipRecloning = false)
{
bool recloned = skipRecloning;
@ -1509,7 +1692,7 @@ private:
case RedisClusterError::ask:
case RedisClusterError::tryagain:
{
USocketExt::write(report.socketAfterError, U_STRING_TO_PARAM(pipeline), 1000);
USocketExt::write(report.socketAfterError, U_STRING_TO_PARAM(pipeline), 500);
}
default:
break;
@ -1536,7 +1719,7 @@ private:
size_t pipelineLength = (pipeline.data() == workingString.data()) ? pipeline.size() : 0;
// U_DUMP("pipelineLength = %lu", pipelineLength);
USocketExt::write(workingSocket, U_STRING_TO_PARAM(pipeline), 1000);
USocketExt::write(workingSocket, U_STRING_TO_PARAM(pipeline), 500);
RedisReadReport report = read(workingSocket, workingString.size(), commandCount);
@ -1679,7 +1862,7 @@ public:
}
while (++it != pipeline.spans.end() && workingSocket == hashslotToSocket[it->hashslot]);
USocketExt::write(workingSocket, U_STRING_TO_PARAM(workingString), 1000);
USocketExt::write(workingSocket, U_STRING_TO_PARAM(workingString), 500);
workingString.setEmpty();
} while (it != pipeline.spans.end());
@ -1751,22 +1934,16 @@ public:
return handleReturn<options>();
}
void clusterUnsubscribe(const UString& channel);
void clusterSubscribe( const UString& channel, vPFcscs callback);
UREDISClusterMaster()
{
clusterNodes = U_NULLPTR;
U_NEW(USocket, managementSocket, USocket);
U_NEW(USocket, subscriptionSocket, USocket);
}
~UREDISClusterMaster()
{
U_DELETE(subscriptionSocket);
U_DELETE(managementSocket);
if (clusterNodes) U_DELETE(clusterNodes);
if (pchannelCallbackMap) U_DELETE(pchannelCallbackMap);
}
#if defined(DEBUG)

View File

@ -24,12 +24,6 @@
# include <ulib/ssl/net/sslsocket.h>
#endif
#ifdef USE_LIBURING
# ifndef U_IO_BUFFER_SIZE
# define U_IO_BUFFER_SIZE U_1M // 1 MB in bytes
# endif
#endif
/**
* @class UClientImage
*
@ -54,9 +48,9 @@ template <class T> class UHashMap;
#define U_ClientImage_request_is_cached UClientImage_Base::cbuffer[0]
#define U_ClientImage_status(obj) (obj)->UClientImage_Base::flag.c[0]
#define U_ClientImage_op_pending(obj) (obj)->UClientImage_Base::flag.c[1]
#define U_ClientImage_write_pending(obj) (obj)->UClientImage_Base::flag.c[2]
#define U_ClientImage_user_value(obj) (obj)->UClientImage_Base::flag.c[3]
#define U_ClientImage_user_value(obj) (obj)->UClientImage_Base::flag.c[1]
#define U_ClientImage_op_pending(obj) (obj)->UClientImage_Base::flag.c[2]
#define U_ClientImage_write_pending(obj) (obj)->UClientImage_Base::flag.c[3]
class U_EXPORT UClientImage_Base : public UEventFd {
public:
@ -311,10 +305,10 @@ public:
_ACCEPT = 0x02,
_READ = 0x04,
_WRITE = 0x08,
_WRITEV = 0x10,
_CLOSE = 0x20,
_CANCEL = 0x40,
_UPDATE = 0x80,
_CLOSE = 0x10,
_CANCEL = 0x20,
_UPDATE = 0x40,
_RECVMSG = 0x80,
_CONNECT = _READ | _ACCEPT
};
@ -325,25 +319,18 @@ public:
op == _ACCEPT ? "_ACCEPT" :
op == _READ ? "_READ" :
op == _WRITE ? "_WRITE" :
op == _WRITEV ? "_WRITEV" :
op == _CLOSE ? "_CLOSE" :
op == _CANCEL ? "_CANCEL" :
op == _UPDATE ? "_UPDATE" :
op == _RECVMSG ? "_RECVMSG" :
op == _CONNECT ? "_CONNECT" : "???");
}
const char* getPendingOperationDescription() { return getPendingOperationDescription( U_ClientImage_op_pending(this)); }
void resetPendingOperation()
bool isPendingOperation()
{
U_TRACE_NO_PARAM(0, "UClientImage_Base::resetPendingOperation()")
U_ClientImage_op_pending(this) = 0;
}
bool isFlagPendingOperation()
{
U_TRACE_NO_PARAM(0, "UClientImage_Base::isFlagPendingOperation()")
U_TRACE_NO_PARAM(0, "UClientImage_Base::isPendingOperation()")
if (U_ClientImage_op_pending(this) != 0) U_RETURN(true);
@ -377,9 +364,19 @@ public:
U_RETURN(false);
}
bool isPendingOperationRead() { return isPendingOperationRead( U_ClientImage_op_pending(this)); }
bool isPendingOperationWrite() { return isPendingOperationWrite(U_ClientImage_op_pending(this)); }
bool isPendingOperationClose() { return isPendingOperationClose(U_ClientImage_op_pending(this)); }
static bool isPendingOperationCancel(char op)
{
U_TRACE(0, "UClientImage_Base::isPendingOperationCancel(%u %B)", op, op)
if ((op & _CANCEL) != 0) U_RETURN(true);
U_RETURN(false);
}
bool isPendingOperationRead() { return isPendingOperationRead( U_ClientImage_op_pending(this)); }
bool isPendingOperationWrite() { return isPendingOperationWrite(U_ClientImage_op_pending(this)); }
bool isPendingOperationClose() { return isPendingOperationClose(U_ClientImage_op_pending(this)); }
bool isPendingOperationCancel() { return isPendingOperationCancel(U_ClientImage_op_pending(this)); }
void setPendingOperationRead()
{
@ -420,7 +417,7 @@ public:
{
U_ClientImage_op_pending(this) &= ~_WRITE;
if (isPendingOperationClose()) U_RETURN(true);
U_RETURN(true);
}
U_RETURN(false);
@ -444,6 +441,31 @@ public:
U_ClientImage_op_pending(this) &= ~_CLOSE;
}
void setPendingOperationCancel()
{
U_TRACE_NO_PARAM(0, "UClientImage_Base::setPendingOperationCancel()")
U_ASSERT_EQUALS(isPendingOperationCancel(), false)
U_ClientImage_op_pending(this) |= _CANCEL;
}
void resetPendingOperationCancel()
{
U_TRACE_NO_PARAM(0, "UClientImage_Base::resetPendingOperationCancel()")
U_DUMP("isPendingOperationCancel() = %b", isPendingOperationCancel())
U_ClientImage_op_pending(this) &= ~_CANCEL;
}
void resetPendingOperation()
{
U_TRACE_NO_PARAM(0, "UClientImage_Base::resetPendingOperation()")
U_ClientImage_op_pending(this) = 0;
}
// flag status processing
enum FlagStatusType {
@ -707,9 +729,10 @@ protected:
int sfd;
uucflag flag;
long last_event;
// HTTP3
#ifdef USE_LIBURING
void* conn;
void* http3;
#endif
bool isCallHandlerFailed();

View File

@ -28,6 +28,7 @@
#ifdef USE_LIBURING
# include <liburing.h>
//#define U_FILES_UPDATE_ASYNC_WORK
#endif
#ifndef SIGWINCH
@ -294,6 +295,8 @@ public:
handler_other->push_back(item);
}
static void addHandlerEventPoll(UEventFd* handler);
static int loadPlugins(UString& plugin_dir, const UString& plugin_list); // load plugin modules and call server-wide hooks handlerConfig()...
// ---------------------------------
@ -1101,12 +1104,27 @@ protected:
static int fds[1];
static int* socketfds;
static UString* rBuffers;
static struct msghdr rmsg;
static UStringRep* rbuffer;
static struct in_pktinfo* pi;
static uint32_t rbuffer_size;
static struct io_uring_sqe* sqe;
static struct io_uring_cqe* cqe;
static struct io_uring* io_uring;
static struct iovec vrwBuffers[3];
static struct io_uring_probe* probe;
static UVector<UEventFd*>* handler_poll;
static char cmbuf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
static void checkIfOpcodeSupported(int op, const char* descr)
{
U_TRACE(1, "UServer_Base::checkIfOpcodeSupported(%d,%S)", op, descr)
if (U_SYSCALL(io_uring_opcode_supported, "%p,%u", probe, op) == false)
{
U_ERROR("%s not supported, kernel(%u)", descr, LINUX_VERSION_CODE)
}
}
static void get_sqe()
{
@ -1152,22 +1170,25 @@ protected:
U_SYSCALL_VOID(io_uring_sqe_set_data, "%p,%p", sqe, (void*)(((long)nClientIndex << 32) + op));
}
static int wait_cqe()
static bool wait_cqe()
{
U_TRACE_NO_PARAM(1, "UServer_Base::wait_cqe()")
int ret = U_SYSCALL(io_uring_wait_cqe, "%p,%p", io_uring, &cqe);
int ret = U_SYSCALL(io_uring_submit_and_wait, "%p,%u", io_uring, 1);
if (ret)
if (ret < 0)
{
if (ret == -EINTR) UInterrupt::checkForEventSignalPending();
else
if (ret == -EINTR)
{
U_ERROR("io_uring_wait_cqe() failed: %d%R", ret, 0); // NB: the last argument (0) is necessary...
UInterrupt::checkForEventSignalPending();
U_RETURN(false);
}
U_ERROR("io_uring_submit_and_wait() failed: %d%R", ret, 0); // NB: the last argument (0) is necessary...
}
U_RETURN(ret);
U_RETURN(true);
}
static void register_files_update()
@ -1188,19 +1209,46 @@ protected:
}
}
static void prepareForAccept()
static void reset()
{
U_TRACE_NO_PARAM(1, "UServer_Base::prepareForAccept()")
U_TRACE_NO_PARAM(0, "UServer_Base::reset()")
U_INTERNAL_DUMP("UNotifier::num_connection = %u UNotifier::max_connection = %u", UNotifier::num_connection, UNotifier::max_connection)
pClientImage->fd = -1;
pClientImage->flag.hi = 0;
U_INTERNAL_ASSERT_MINOR(UNotifier::num_connection, UNotifier::max_connection)
register_files_update();
}
USocket::resetPeerAddr();
static void prepareForCancelRead()
{
U_TRACE_NO_PARAM(1, "UServer_Base::prepareForCancelRead()")
U_SYSCALL_VOID(io_uring_prep_accept, "%p,%u,%p,%p,%u", sqe, 0, (struct sockaddr*)&USocket::peer_addr, &USocket::peer_addr_len, SOCK_CLOEXEC);
pClientImage->setPendingOperationCancel();
nClientIndex = 0;
get_sqe();
U_SYSCALL_VOID(io_uring_prep_cancel, "%p,%p,%u", sqe, (void*)(((long)nClientIndex << 32) + (long)UClientImage_Base::_READ), 0);
U_SYSCALL_VOID(io_uring_sqe_set_data, "%p,%p", sqe, (void*)(((long)nClientIndex << 32) + (long)UClientImage_Base::_CANCEL));
submit();
}
static void prepareFilesUpdate()
{
U_TRACE_NO_PARAM(1, "UServer_Base::prepareFilesUpdate()")
# ifndef U_FILES_UPDATE_ASYNC_WORK
register_files_update();
# else
get_sqe();
U_SYSCALL_VOID(io_uring_prep_files_update, "%p,%p,%u,%u", sqe, &(fds[0] = pClientImage->fd), 1, 1+nClientIndex);
U_SYSCALL_VOID(io_uring_sqe_set_flags, "%p,%u", sqe, IOSQE_IO_LINK); // That next SQE will not be started before this one completes
U_SYSCALL_VOID(io_uring_sqe_set_data, "%p,%p", sqe, (void*)(((long)nClientIndex << 32) + UClientImage_Base::_UPDATE));
# endif
}
static void epoll_ctl_batch(UEventFd* handler)
@ -1220,8 +1268,9 @@ protected:
U_SYSCALL_VOID(io_uring_prep_epoll_ctl, "%p,%d,%d,%u,%p", sqe, UNotifier::epollfd, handler->fd, EPOLL_CTL_ADD, &ev);
}
static void submit(int op, ...);
static void findNextClientImage();
static void logNewClient();
static void findClientImage();
static void prepareOperation(int op, ...);
static void waitForEvent(UEventTime* ptimeout);
static void epoll_ctl_batch(uint32_t ctl_cmd_cnt);
#endif

View File

@ -621,6 +621,15 @@ public:
U_RETURN(false);
}
void setPktInfo()
{
U_TRACE_NO_PARAM(0, "USocket::setPktInfo()")
# ifdef IP_PKTINFO
(void) setSockOpt(IPPROTO_IP, IP_PKTINFO, (const int[]){ 1 });
# endif
}
/**
* The recvfrom() function is called with the proper parameters, params is placed for obtaining
* the source address information. The number of bytes read is returned
@ -856,7 +865,30 @@ protected:
peer_addr_len = sizeof(peer_addr);
(void) U_SYSCALL(memset, "%p,%d,%u", &peer_addr, 0, U_SIZE_SOCKADDR);
(void) U_SYSCALL(memset, "%p,%u,%u", &peer_addr, 0, U_SIZE_SOCKADDR);
}
void resetPeerAddrFromLocal()
{
U_TRACE_NO_PARAM(0, "USocket::resetPeerAddrFromLocal()")
resetPeerAddr();
uint32_t iAddressLength;
# ifdef ENABLE_IPV6
if (U_socket_IPv6(this)) iAddressLength = sizeof(in6_addr);
else
# endif
{
iAddressLength = sizeof(in_addr);
}
char* ptr = (char*)&peer_addr;
u_put_unalignedp16(ptr, cLocalAddress.getAddressFamily());
U_MEMCPY(ptr+sizeof(short), (const void*)&(cLocalAddress.pcAddress.p), iAddressLength);
}
/**

View File

@ -104,7 +104,6 @@ class UValue;
class UString;
class UBase64;
class UEscape;
class UIORing;
class UHexDump;
class UOptions;
class UTimeDate;
@ -2811,7 +2810,6 @@ private:
}
friend class UHTTP;
friend class UIORing;
friend class USSEThread;
friend class UServer_Base;
friend class URDBClient_Base;
@ -2899,17 +2897,16 @@ template <> inline uint32_t UObject2String<UString>(UString& object, char* pbuff
// by Victor Stewart
#if defined(U_STDCPP_ENABLE)
# if defined(HAVE_CXX11)
#if defined(U_STDCPP_ENABLE) && defined(HAVE_CXX11)
namespace std {
template<> struct hash<UString> {
std::size_t operator()(const UString& str) const noexcept { return str.hash(); }
};
}
# endif
#endif
#if defined(HAVE_CXX20) && defined(U_LINUX) && !defined(__clang__)
# include <utility> // std::index_sequence
#if defined(U_STDCPP_ENABLE) && defined(HAVE_CXX20) && defined(U_LINUX) && !defined(__clang__)
# include <utility> // std::index_sequence
template <char... Chars>
class UCompileTimeStringView {
private:
@ -3208,24 +3205,19 @@ public:
}
};
# if defined(U_STDCPP_ENABLE) && defined(HAVE_CXX20) && defined(U_LINUX) && !defined(__clang__) && GCC_VERSION_NUM < 100100
# if defined(U_STDCPP_ENABLE) && defined(HAVE_CXX20) && defined(U_LINUX) && !defined(__clang__)
template<typename T>
concept bool UCompileTimeStringType = requires(T string) {
is_ctv_v<T>;
};
concept UCompileTimeStringType = is_ctv_v<T>;
template<typename T>
concept bool UStringType = requires(T string)
{
(std::is_same_v<T, UString> || is_ctv_v<T>);
};
concept UStringType = (std::is_same_v<std::remove_reference_t<T>, UString> || is_ctv_v<T>);
inline bool operator==(const UString& lhs, const UCompileTimeStringType& rhs){ return lhs.equal(rhs.string); }
inline bool operator==(const UCompileTimeStringType& lhs, const UString& rhs){ return rhs.equal(lhs.string); }
inline bool operator==(const UString& lhs, const UCompileTimeStringType auto& rhs){ return lhs.equal(rhs.string); }
inline bool operator==(const UCompileTimeStringType auto& lhs, const UString& rhs){ return rhs.equal(lhs.string); }
inline bool operator!=(const UString& lhs, const UCompileTimeStringType auto& rhs){ return !lhs.equal(rhs.string); }
inline bool operator!=(const UCompileTimeStringType auto& lhs, const UString& rhs){ return !rhs.equal(lhs.string); }
inline bool operator!=(const UString& lhs, const UCompileTimeStringType& rhs){ return !lhs.equal(rhs.string); }
inline bool operator!=(const UCompileTimeStringType& lhs, const UString& rhs){ return !rhs.equal(lhs.string); }
# endif
# endif
#endif
#endif

View File

@ -15,14 +15,20 @@
#define ULIB_HTTP3_H 1
#include <ulib/db/rdb.h>
#include <ulib/notifier.h>
#include <ulib/net/server/server.h>
#include <quiche.h>
#define U_MAX_TOKEN_LEN \
sizeof("quiche")-1 + \
sizeof(struct sockaddr_storage) + \
QUICHE_MAX_CONN_ID_LEN
#define U_LOCAL_CONN_ID_LEN 16
class UHTTP;
class UHttpPlugIn;
class UServer_Base;
class UClientImage_Base;
/**
@ -54,20 +60,19 @@ public:
quiche_h3_conn* http3;
} conn_io;
static bool handlerRead();
static bool handlerAccept();
static int loadConfigParam();
static bool handlerNewConnection();
protected:
static conn_io conn;
static size_t conn_id_len;
static uint8_t pkt_type;
static quiche_config* qconfig;
static quiche_h3_config* http3_config;
static struct sockaddr_storage peer_addr;
static uint8_t conn_id[QUICHE_MAX_CONN_ID_LEN];
static uint32_t quiche_max_packet_size, peer_addr_len;
static UHashMap<UClientImage_Base*>* peers;
static size_t conn_id_len, scid_len, token_len;
static uint32_t pkt_version, quiche_max_packet_size, peer_addr_len;
static uint8_t token[U_MAX_TOKEN_LEN], scid[QUICHE_MAX_CONN_ID_LEN], conn_id[QUICHE_MAX_CONN_ID_LEN];
// SERVICES
@ -90,6 +95,29 @@ protected:
if (http3_config) U_SYSCALL_VOID(quiche_h3_config_free, "%p", http3_config);
}
static bool parseHeader(const char* data, uint32_t iBytesRead);
// Lookup a connection based on the packet's connection ID
static bool lookup()
{
U_TRACE_NO_PARAM(0, "UHTTP3::lookup()")
if (peers->empty() == false &&
((UServer_Base::pClientImage = peers->at((const char*)conn_id, conn_id_len))))
{
UServer_Base::nClientIndex = UServer_Base::pClientImage - UServer_Base::vClientImage;
U_INTERNAL_DUMP("UServer_Base::nClientIndex = %u", UServer_Base::nClientIndex)
U_INTERNAL_ASSERT_MINOR(UServer_Base::nClientIndex, UNotifier::max_connection)
U_RETURN(true);
}
U_RETURN(false);
}
static int for_each_header(uint8_t* name, size_t name_len, uint8_t* value, size_t value_len, void* argp)
{
U_TRACE(0, "UHTTP3::for_each_header(%.*S,%u,%.*S,%u,%p)", name_len, name, name_len, value_len, value, value_len, argp)
@ -114,6 +142,7 @@ private:
friend class UHTTP;
friend class Application;
friend class UHttpPlugIn;
friend class UServer_Base;
friend class UClientImage_Base;
};
#endif

View File

@ -155,10 +155,14 @@ public:
static void startResolv(const char* name, int family = AF_INET); // AF_INET6
#endif
// write data
static uint32_t write(USocket* sk, const UString& buffer, int timeoutMS) { return write(sk, U_STRING_TO_PARAM(buffer), timeoutMS); }
static uint32_t write(USocket* sk, const char* ptr, uint32_t count, int timeoutMS);
static bool read(USocket* sk, UString& buffer, uint32_t count = U_SINGLE_READ, int timeoutMS = -1, uint32_t time_limit = 0); // read while not received almost count data
private:
friend class UREDISClusterMaster;
#ifdef USE_C_ARES
static int resolv_status;
static char resolv_hostname[INET6_ADDRSTRLEN];
@ -178,8 +182,6 @@ private:
static uint32_t byte_read, start_read;
static bool read(USocket* sk, UString& buffer, uint32_t count = U_SINGLE_READ, int timeoutMS = -1, uint32_t time_limit = 0); // read while not received almost count data
// read while received data
static void readEOF(USocket* sk, UString& buffer)
@ -193,11 +195,6 @@ private:
static uint32_t readWhileNotToken(USocket* sk, UString& buffer, const char* token, uint32_t token_len, int timeoutMS = -1);
// write data
static uint32_t write(USocket* sk, const UString& buffer, int timeoutMS) { return write(sk, U_STRING_TO_PARAM(buffer), timeoutMS); }
static uint32_t write(USocket* sk, const char* ptr, uint32_t count, int timeoutMS);
// write data from multiple buffers
static uint32_t iov_resize(struct iovec* liov, const struct iovec* iov, int iovcnt, uint32_t byte_written);

View File

@ -66,7 +66,7 @@ bool UREDISClient_Base::connect(const char* phost, unsigned int _port)
UClient_Base::connect())
{
init();
U_RETURN(true);
}
@ -352,13 +352,13 @@ bool UREDISClient_Base::deleteKeys(const char* pattern, uint32_t len) // Delete
// by Victor Stewart
#if defined(U_STDCPP_ENABLE) && defined(HAVE_CXX20) && defined(U_LINUX) && !defined(__clang__) && GCC_VERSION_NUM < 100100
#if defined(U_STDCPP_ENABLE) && defined(HAVE_CXX20) && defined(U_LINUX) && !defined(__clang__)
int UREDISClusterMaster::handlerRead()
int RedisSubscriber::handlerRead()
{
// BytesRead(100) = "*3\r\n$7\r\nmessage\r\n$19\r\n{ABC}.trafficSignal\r\n$1\r\n1\r\n*3\r\n$7\r\nmessage\r\n$19\r\n{DEF}.trafficSignal\r\n$1\r\n1\r\n"
U_TRACE_NO_PARAM(0, "UREDISClusterMaster::handlerRead()")
U_TRACE_NO_PARAM(0, "RedisSubscriber::handlerRead()")
if (subscriptionString.size()) subscriptionString.setEmpty();
USocketExt::read(subscriptionSocket, subscriptionString, U_SINGLE_READ, 1000);
@ -399,28 +399,6 @@ int UREDISClusterMaster::handlerRead()
U_RETURN(U_NOTIFIER_OK);
}
void UREDISClusterMaster::clusterUnsubscribe(const UString& channel) // unregister the callback for messages published to the given channels
{
U_TRACE(0, "UREDISClusterMaster::clusterUnsubscribe(%V)", channel.rep)
if (subscriptionString.size()) subscriptionString.setEmpty();
UCompileTimeRESPEncoder::encode<"UNSUBSCRIBE {}"_ctv>(subscriptionString, channel);
USocketExt::write(subscriptionSocket, U_STRING_TO_PARAM(subscriptionString), 1000);
(void)pchannelCallbackMap->erase(channel);
}
void UREDISClusterMaster::clusterSubscribe(const UString& channel, vPFcscs callback) // register the callback for messages published to the given channels
{
U_TRACE(0, "UREDISClusterMaster::clusterSubscribe(%V,%p)", channel.rep, callback)
if (subscriptionString.size()) subscriptionString.setEmpty();
UCompileTimeRESPEncoder::encode<"SUBSCRIBE {}"_ctv>(subscriptionString, channel);
USocketExt::write(subscriptionSocket, U_STRING_TO_PARAM(subscriptionString), 1000);
UString channelCopy(U_STRING_TO_PARAM(channel));
pchannelCallbackMap->insert(channelCopy, (const void*)callback);
}
void UREDISClusterMaster::cloneClusterTopology()
{
U_TRACE_NO_PARAM(0, "UREDISClusterMaster::cloneClusterTopology()")
@ -535,24 +513,15 @@ bool UREDISClusterMaster::connect(const UString& host, uint16_t port)
{
U_TRACE(0, "UREDISClusterMaster::connect(%v,%hhu)", host.rep, port)
// const UString& singleTest = single()
if (managementSocket->connectServer(host, port, 1000))
{
cloneClusterTopology();
RedisClusterNode *randomNode = clusterNodes->randomElement();
if (randomNode)
if (randomNode)
{
subscriptionSocket->connectServer(randomNode->ipAddress, randomNode->port, 1000);
U_NEW(UHashMap<void*>, pchannelCallbackMap, UHashMap<void*>());
this->UEventFd::fd = subscriptionSocket->getFd();
this->UEventFd::op_mask |= EPOLLET;
UServer_Base::addHandlerEvent(this);
RedisSubscriber::connectForSubscriptions(randomNode->ipAddress, randomNode->port);
U_RETURN(true);
}
}

View File

@ -139,8 +139,10 @@ UClientImage_Base::UClientImage_Base()
flag.u = 0;
last_event = u_now->tv_sec;
conn = U_NULLPTR;
#ifdef USE_LIBURING
conn =
http3 = U_NULLPTR;
#endif
// NB: array are not pointers (virtual table can shift the address of 'this')...
@ -182,8 +184,16 @@ void UClientImage_Base::set()
socket->cLocalAddress.set(UServer_Base::socket->cLocalAddress);
}
socket->flags |= O_CLOEXEC;
socket->flags |= O_CLOEXEC;
#ifdef USE_LIBURING
if (UServer_Base::brng == false)
#endif
{
#ifdef HAVE_ACCEPT4
if (USocket::accept4_flags & SOCK_NONBLOCK) socket->flags |= O_NONBLOCK;
#endif
}
#ifdef DEBUG
U_CHECK_MEMORY
@ -283,20 +293,15 @@ void UClientImage_Base::init()
U_INTERNAL_ASSERT_EQUALS(chronometer, U_NULLPTR)
#ifdef USE_LIBURING
if (UServer_Base::brng)
if (UServer_Base::brng ||
UServer_Base::budp)
{
U_NEW_STRING(rbuffer, UString(UServer_Base::rbuffer));
}
else
#endif
{
uint32_t sz = 8192;
#ifdef USERVER_UDP
if (UServer_Base::budp) sz = 65535;
#endif
U_NEW_STRING(rbuffer, UString(sz));
U_NEW_STRING(rbuffer, UString(8192));
}
U_NEW_STRING(body, UString);
@ -608,12 +613,7 @@ void UClientImage_Base::handlerDelete()
if (data_pending)
{
# ifdef USE_LIBURING
if (UServer_Base::brng == false)
# endif
{
U_DELETE(data_pending)
}
data_pending = U_NULLPTR;
}
@ -642,15 +642,29 @@ void UClientImage_Base::handlerDelete()
reset();
}
#ifdef USE_LIBURING
if (UServer_Base::brng)
{
flag.lo = 0;
resetPendingOperationClose();
}
else
#endif
{
flag.u = 0;
UEventFd::fd = -1;
#ifdef HAVE_ACCEPT4
U_INTERNAL_ASSERT_EQUALS(((USocket::accept4_flags & SOCK_NONBLOCK) != 0),((socket->flags & O_NONBLOCK) != 0))
#endif
}
U_INTERNAL_ASSERT_EQUALS(data_pending, U_NULLPTR)
U_INTERNAL_ASSERT_EQUALS(UEventFd::op_mask, EPOLLIN | EPOLLRDHUP | EPOLLET)
#ifdef HAVE_ACCEPT4
U_INTERNAL_ASSERT_EQUALS(((USocket::accept4_flags & SOCK_CLOEXEC) != 0),((socket->flags & O_CLOEXEC) != 0))
U_INTERNAL_ASSERT_EQUALS(((USocket::accept4_flags & SOCK_NONBLOCK) != 0),((socket->flags & O_NONBLOCK) != 0))
U_INTERNAL_ASSERT_EQUALS(((USocket::accept4_flags & SOCK_CLOEXEC) != 0),((socket->flags & O_CLOEXEC) != 0))
#endif
#ifdef USE_LIBEVENT
@ -1156,7 +1170,9 @@ bool UClientImage_Base::genericRead()
#endif
#ifdef USE_LIBURING
if (UServer_Base::brng == false)
if (UServer_Base::brng == false ||
(U_ClientImage_request == 0 &&
U_ClientImage_parallelization == U_PARALLELIZATION_CHILD))
#endif
{
// NB: rbuffer string can be referenced more than one (often if U_SUBSTR_INC_REF is defined)...
@ -1236,7 +1252,7 @@ uint32_t UClientImage_Base::writev(struct iovec* iov, int iovcnt, uint32_t _coun
{
U_DUMP_IOVEC(iov,iovcnt)
UServer_Base::submit(_WRITEV, iov, iovcnt, 0); // this queues a writev()
UServer_Base::prepareOperation(_WRITE, iov, iovcnt, 0);
U_RETURN(_count);
}
@ -1280,8 +1296,6 @@ start:
if (genericRead() == false)
{
U_INTERNAL_ASSERT_EQUALS(UServer_Base::brng, false)
if (U_ClientImage_state == U_PLUGIN_HANDLER_AGAIN &&
U_ClientImage_parallelization != U_PARALLELIZATION_CHILD)
{
@ -2056,7 +2070,10 @@ void UClientImage_Base::abortive_close()
if (U_ClientImage_pipeline) resetPipeline();
if (UServer_Base::csocket->isOpen()) UServer_Base::csocket->abortive_close();
if (UServer_Base::csocket->isOpen())
{
UServer_Base::csocket->abortive_close();
}
}
void UClientImage_Base::resetPipeline()

File diff suppressed because it is too large Load Diff

View File

@ -240,12 +240,10 @@ void USocket::setRemoteAddressAndPort()
{
U_TRACE_NO_PARAM(0, "USocket::setRemoteAddressAndPort()")
U_INTERNAL_DUMP("peer_addr_len = %u sizeOf() = %u", peer_addr_len, ((SocketAddress*)&peer_addr)->sizeOf())
U_INTERNAL_DUMP("peer_addr_len = %u sizeOf() = %u SocketAddress = %#.*S", peer_addr_len, ((SocketAddress*)&peer_addr)->sizeOf(), peer_addr_len, &peer_addr)
U_INTERNAL_ASSERT_EQUALS(peer_addr_len, ((SocketAddress*)&peer_addr)->sizeOf())
U_INTERNAL_DUMP("SocketAddress = %#.*S", peer_addr_len, &peer_addr)
iRemotePort = ((SocketAddress*)&peer_addr)->getPortNumber();
((SocketAddress*)&peer_addr)->getIPAddress(cRemoteAddress);
@ -931,12 +929,14 @@ void USocket::close_socket()
#if defined(HAVE_EPOLL_WAIT) && !defined(USE_LIBEVENT)
U_INTERNAL_DUMP("U_ClientImage_parallelization = %d", U_ClientImage_parallelization)
if (U_ClientImage_parallelization != U_PARALLELIZATION_CHILD &&
UNotifier::isHandler(iSockDesc))
if (U_ClientImage_parallelization != U_PARALLELIZATION_CHILD)
{
(void) U_FF_SYSCALL(epoll_ctl, "%d,%d,%d,%p", UNotifier::epollfd, EPOLL_CTL_DEL, iSockDesc, (struct epoll_event*)1);
if (UNotifier::isHandler(iSockDesc))
{
(void) U_FF_SYSCALL(epoll_ctl, "%d,%d,%d,%p", UNotifier::epollfd, EPOLL_CTL_DEL, iSockDesc, (struct epoll_event*)1);
UNotifier::handlerDelete(iSockDesc, EPOLLIN | EPOLLRDHUP);
UNotifier::handlerDelete(iSockDesc, EPOLLIN | EPOLLRDHUP);
}
}
#endif

View File

@ -21,8 +21,14 @@
#define U_MAX_DATAGRAM_SIZE 1350
size_t UHTTP3::scid_len;
size_t UHTTP3::token_len;
size_t UHTTP3::conn_id_len;
uint8_t UHTTP3::pkt_type;
uint8_t UHTTP3::token[U_MAX_TOKEN_LEN];
uint8_t UHTTP3::scid[QUICHE_MAX_CONN_ID_LEN];
uint8_t UHTTP3::conn_id[QUICHE_MAX_CONN_ID_LEN];
uint32_t UHTTP3::pkt_version;
uint32_t UHTTP3::peer_addr_len;
uint32_t UHTTP3::quiche_max_packet_size = U_MAX_DATAGRAM_SIZE;
quiche_config* UHTTP3::qconfig;
@ -177,352 +183,267 @@ int UHTTP3::loadConfigParam()
U_RETURN(U_PLUGIN_HANDLER_OK);
}
bool UHTTP3::handlerRead()
bool UHTTP3::parseHeader(const char* data, uint32_t iBytesRead)
{
U_TRACE_NO_PARAM(0, "UHTTP3::handlerRead()")
U_TRACE(0, "UHTTP3::parseHeader(%.*S,%u)", iBytesRead, data, iBytesRead)
scid_len =
conn_id_len = QUICHE_MAX_CONN_ID_LEN;
token_len = U_MAX_TOKEN_LEN;
// Extracts version, type, source / destination connection ID and address verification token from the packet in buffer
int rc = U_SYSCALL(quiche_header_info, "%p,%u,%u,%p,%p,%p,%p,%p,%p,%p,%p", (const uint8_t*)data, iBytesRead, U_LOCAL_CONN_ID_LEN,
&pkt_version, &pkt_type, scid, &scid_len, conn_id, &conn_id_len, token, &token_len);
if (rc < 0)
{
U_DEBUG("UHTTP3::parseHeader(): failed to parse header: %d", rc);
U_RETURN(false);
}
U_INTERNAL_DUMP("\n"
" scid(%u) = %#.*S\n"
" token(%u) = %#.*S\n"
"conn_id(%u) = %#.*S\n"
"pkt_version = %u pkt_type = %u",
scid_len, scid_len, scid, token_len, token_len, token, conn_id_len, conn_id_len, conn_id, pkt_version, pkt_type)
U_RETURN(true);
}
bool UHTTP3::handlerNewConnection()
{
U_TRACE_NO_PARAM(0, "UHTTP3::handlerNewConnection()")
U_INTERNAL_ASSERT_POINTER(peers)
U_INTERNAL_ASSERT(UServer_Base::budp)
int rc;
void* pconn;
uint8_t pkt_type;
uint32_t pkt_version;
size_t scid_len, token_len;
ssize_t done, written, sent;
char* data = UClientImage_Base::rbuffer->data();
int iBytesRead, fd = UServer_Base::socket->getFd();
uint8_t token[U_MAX_TOKEN_LEN], scid[QUICHE_MAX_CONN_ID_LEN], out[U_MAX_DATAGRAM_SIZE];
ssize_t written, sent;
const char* pkt = "vneg";
uint8_t out[U_MAX_DATAGRAM_SIZE];
while (true)
if (pkt_type != Initial)
{
USocket::resetPeerAddr();
U_DEBUG("UHTTP3::handlerNewConnection(): packet is NOT initial: %u", pkt_type);
iBytesRead = U_SYSCALL(recvfrom, "%d,%p,%u,%u,%p,%p", fd, data, 65535, 0, (struct sockaddr*)&peer_addr, &peer_addr_len);
U_RETURN(false);
}
if (iBytesRead <= 0)
// Client Initial packets must be at least 1200 bytes
if (UServer_Base::rbuffer->size() < QUICHE_MIN_CLIENT_INITIAL_LEN)
{
U_DEBUG("UHTTP3::handlerNewConnection(): quic initial packet is too short: %u", UServer_Base::rbuffer->size());
U_RETURN(false);
}
// Returns true if the given protocol version is supported
if (U_SYSCALL(quiche_version_is_supported, "%u", pkt_version) == false)
{
U_DEBUG("UHTTP3::handlerNewConnection(): version negotiation");
// Writes a version negotiation packet
written = U_SYSCALL(quiche_negotiate_version, "%p,%u,%p,%u,%p,%u", scid, scid_len, conn_id, conn_id_len, out, sizeof(out));
pkt: if (written < 0)
{
if (errno != EAGAIN)
{
U_DEBUG("UHTTP3::handlerRead(): failed to receive");
U_RETURN(false);
}
break;
}
U_INTERNAL_DUMP("BytesRead(%u) = %#.*S", iBytesRead, iBytesRead, data)
u__memcpy(&USocket::peer_addr, &peer_addr, USocket::peer_addr_len = peer_addr_len, __PRETTY_FUNCTION__);
scid_len =
conn_id_len = QUICHE_MAX_CONN_ID_LEN;
token_len = U_MAX_TOKEN_LEN;
// Extracts version, type, source / destination connection ID and address verification token from the packet in buffer
rc = U_SYSCALL(quiche_header_info, "%p,%u,%u,%p,%p,%p,%p,%p,%p,%p,%p", (const uint8_t*)data, iBytesRead, U_LOCAL_CONN_ID_LEN,
&pkt_version, &pkt_type, scid, &scid_len, conn_id, &conn_id_len, token, &token_len);
if (rc < 0)
{
U_DEBUG("UHTTP3::handlerRead(): failed to parse header: %d", rc);
U_DEBUG("UHTTP3::handlerNewConnection(): failed to create %S packet: %d", pkt, written);
U_RETURN(false);
}
U_INTERNAL_DUMP("\n"
" scid(%u) = %#.*S\n"
" token(%u) = %#.*S\n"
"conn_id(%u) = %#.*S\n"
"pkt_version = %d pkt_type = %d",
scid_len, scid_len, scid, token_len, token_len, token, conn_id_len, conn_id_len, conn_id, pkt_version, pkt_type)
sent = U_SYSCALL(sendto, "%u,%p,%u,%u,%p,%d", UServer_Base::fds[0], out, written, 0, (struct sockaddr*)&USocket::peer_addr, USocket::peer_addr_len);
// Lookup a connection based on the packet's connection ID. If there is no connection matching, create a new one
pconn = (peers->empty() ? U_NULLPTR : peers->at((const char*)conn_id, conn_id_len));
U_INTERNAL_DUMP("pconn = %p", pconn)
if (pconn == U_NULLPTR)
if (sent == written)
{
const char* pkt = "vneg";
if (pkt_type != Initial)
{
U_DEBUG("UHTTP3::handlerRead(): packet is NOT initial: %d", pkt_type);
continue;
}
// Client Initial packets must be at least 1200 bytes
if (iBytesRead < QUICHE_MIN_CLIENT_INITIAL_LEN)
{
U_DEBUG("UHTTP3::handlerRead(): quic initial packet is too short: %d", iBytesRead);
continue;
}
// Returns true if the given protocol version is supported
if (U_SYSCALL(quiche_version_is_supported, "%u", pkt_version) == false)
{
U_DEBUG("UHTTP3::handlerRead(): version negotiation");
// Writes a version negotiation packet
written = U_SYSCALL(quiche_negotiate_version, "%p,%u,%p,%u,%p,%u", scid, scid_len, conn_id, conn_id_len, out, sizeof(out));
pkt: if (written < 0)
{
U_DEBUG("UHTTP3::handlerRead(): failed to create %s packet: %d", pkt, written);
U_RETURN(false);
}
sent = U_SYSCALL(sendto, "%d,%p,%u,%u,%p,%d", fd, out, written, 0, (struct sockaddr*)&peer_addr, peer_addr_len);
if (sent == written)
{
U_DEBUG("UHTTP3::handlerRead(): sent %u bytes", sent);
}
else
{
U_DEBUG("UHTTP3::handlerRead(): failed to send");
}
U_RETURN(false);
}
if (token_len == 0)
{
uint8_t odcid[QUICHE_MAX_CONN_ID_LEN];
// Generate a stateless retry token. The token includes the static string `"quiche"` followed
// by the IP address of the client and by the original destination connection ID generated by the client
U_DEBUG("UHTTP3::handlerRead(): stateless retry");
(void) memcpy(token, U_CONSTANT_TO_PARAM("quiche"));
(void) memcpy(token + U_CONSTANT_SIZE("quiche"), &peer_addr, peer_addr_len);
(void) memcpy(token + U_CONSTANT_SIZE("quiche") + peer_addr_len, conn_id, conn_id_len);
token_len = U_CONSTANT_SIZE("quiche") + peer_addr_len + conn_id_len;
u__memcpy(odcid, conn_id, conn_id_len, __PRETTY_FUNCTION__);
// Writes a retry packet
written = U_SYSCALL(quiche_retry, "%p,%u,%p,%u,%p,%u,%p,%u,%p,%u", scid, scid_len, conn_id, conn_id_len, odcid, conn_id_len, token, token_len, out, sizeof(out));
pkt = "retry";
goto pkt;
}
// Validates a stateless retry token. This checks that the ticket includes the `"quiche"` static string, and that the client IP address matches the address stored in the ticket
if (token_len < U_CONSTANT_SIZE("quiche") ||
memcmp(token, U_CONSTANT_TO_PARAM("quiche")))
{
U_DEBUG("UHTTP3::handlerRead(): invalid address validation token");
U_RETURN(false);
}
token_len -= U_CONSTANT_SIZE("quiche");
const char* ptr = (const char*)&token[0] + U_CONSTANT_SIZE("quiche");
if (token_len < peer_addr_len ||
memcmp(ptr, &peer_addr, peer_addr_len))
{
U_DEBUG("UHTTP3::handlerRead(): invalid address validation token");
U_RETURN(false);
}
ptr += peer_addr_len;
token_len -= peer_addr_len;
if (conn_id_len != token_len) // The token was not valid, meaning the retry failed, so drop the packet
{
U_DEBUG("UHTTP3::handlerRead(): invalid address validation token");
U_RETURN(false);
}
U_INTERNAL_ASSERT_EQUALS(conn.conn, U_NULLPTR)
// Reuse the source connection ID we sent in the Retry packet, instead of changing it again. Creates a new server-side connection
conn.conn = (quiche_conn*) U_SYSCALL(quiche_accept, "%p,%u,%p,%u,%p", conn_id, conn_id_len, (const uint8_t*)ptr, token_len, qconfig);
if (conn.conn == U_NULLPTR)
{
U_DEBUG("UHTTP3::handlerRead(): failed to create connection");
U_RETURN(false);
}
peers->insert((const char*)conn_id, conn_id_len, (const UClientImage_Base*)&conn);
U_DEBUG("UHTTP3::handlerNewConnection(): sent %u bytes", sent);
}
// Processes QUIC packets received from the peer
done = U_SYSCALL(quiche_conn_recv, "%p,%p,%u", conn.conn, (uint8_t*)data, iBytesRead);
if (done == QUICHE_ERR_DONE)
else
{
U_DEBUG("UHTTP3::handlerRead(): done reading");
U_RETURN(true);
}
if (done < 0)
{
U_DEBUG("UHTTP3::handlerRead(): failed to process packet: %d", done);
U_DEBUG("UHTTP3::handlerNewConnection(): failed to send");
U_RETURN(false);
}
U_DEBUG("UHTTP3::handlerRead(): recv %d bytes", done);
if (U_SYSCALL(quiche_conn_is_in_early_data, "%p", conn.conn) || // the connection has a pending handshake that has progressed
U_SYSCALL(quiche_conn_is_established, "%p", conn.conn)) // the connection handshake is complete
{
U_DEBUG("UHTTP3::handlerRead(): connection handshake is complete");
U_INTERNAL_ASSERT_EQUALS(conn.http3, U_NULLPTR)
// Creates a new HTTP/3 connection using the provided QUIC connection
conn.http3 = (quiche_h3_conn*) U_SYSCALL(quiche_h3_conn_new_with_transport, "%p,%p", conn.conn, http3_config);
if (conn.http3 == U_NULLPTR)
{
U_DEBUG("UHTTP3::handlerAccept(): failed to create HTTP/3 connection");
U_RETURN(false);
}
quiche_h3_event* ev;
while (true)
{
// Processes HTTP/3 data received from the peer
done = U_SYSCALL(quiche_h3_conn_poll, "%p,%p,%p", conn.http3, conn.conn, &ev);
if (done < 0) break;
switch (quiche_h3_event_type(ev))
{
case QUICHE_H3_EVENT_HEADERS:
{
// Iterates over the headers in the event. The `cb` callback will be called for each header in `ev`. `cb` should check the validity of
// pseudo-headers and headers. If `cb` returns any value other than `0`, processing will be interrupted and the value is returned to the caller
rc = U_SYSCALL(quiche_h3_event_for_each_header, "%p,%p,%p", ev, for_each_header, NULL);
if (rc != 0)
{
U_DEBUG("UHTTP3::handlerRead(): failed to process headers");
}
/*
quiche_h3_header headers[] = {
{
.name = (const uint8_t *) ":status",
.name_len = sizeof(":status") - 1,
.value = (const uint8_t *) "200",
.value_len = sizeof("200") - 1,
},
{
.name = (const uint8_t *) "server",
.name_len = sizeof("server") - 1,
.value = (const uint8_t *) "quiche",
.value_len = sizeof("quiche") - 1,
},
{
.name = (const uint8_t *) "content-length",
.name_len = sizeof("content-length") - 1,
.value = (const uint8_t *) "5",
.value_len = sizeof("5") - 1,
},
};
quiche_h3_send_response(conn_io->http3, conn_io->conn, s, headers, 3, true);
quiche_h3_send_body(conn_io->http3, conn_io->conn, s, (uint8_t *) "byez\n", 5, true);
*/
break;
}
case QUICHE_H3_EVENT_DATA:
{
U_DEBUG("UHTTP3::handlerRead(): got HTTP data");
break;
}
case QUICHE_H3_EVENT_FINISHED:
break;
}
U_SYSCALL_VOID(quiche_h3_event_free, "%p", ev);
}
}
}
while (true)
if (token_len == 0)
{
written = U_SYSCALL(quiche_conn_send, "%p,%p,%u", conn.conn, out, sizeof(out));
uint8_t odcid[QUICHE_MAX_CONN_ID_LEN];
if (written == QUICHE_ERR_DONE)
{
U_DEBUG("UHTTP3::handlerRead(): done writing");
// Generate a stateless retry token. The token includes the static string "quiche" followed
// by the IP address of the client and by the original destination connection ID generated by the client
U_RETURN(false);
}
U_DEBUG("UHTTP3::handlerNewConnection(): stateless retry");
if (written < 0)
{
U_DEBUG("UHTTP3::handlerRead(): failed to create packet: %d", written);
(void) memcpy(token, U_CONSTANT_TO_PARAM("quiche"));
(void) memcpy(token + U_CONSTANT_SIZE("quiche"), &USocket::peer_addr, USocket::peer_addr_len);
(void) memcpy(token + U_CONSTANT_SIZE("quiche") + USocket::peer_addr_len, conn_id, conn_id_len);
U_RETURN(false);
}
token_len = U_CONSTANT_SIZE("quiche") + USocket::peer_addr_len + conn_id_len;
sent = U_SYSCALL(sendto, "%d,%p,%u,%u,%p,%d", fd, out, written, 0, (struct sockaddr*)&USocket::peer_addr, USocket::peer_addr_len);
u__memcpy(odcid, conn_id, conn_id_len, __PRETTY_FUNCTION__);
if (sent != written)
{
U_DEBUG("UHTTP3::handlerRead(): failed to send");
// Writes a retry packet
written = U_SYSCALL(quiche_retry, "%p,%u,%p,%u,%p,%u,%p,%u,%p,%u", scid, scid_len, conn_id, conn_id_len, odcid, conn_id_len, token, token_len, out, sizeof(out));
U_RETURN(false);
}
pkt = "retry";
U_DEBUG("UHTTP3::handlerRead(): sent %u bytes", sent);
goto pkt;
}
// UClientImage_Base::rbuffer->size_adjust(iBytesRead);
// Validates a stateless retry token. This checks that the ticket includes the `"quiche"` static string, and that the client IP address matches the address stored in the ticket
if (token_len < U_CONSTANT_SIZE("quiche") ||
memcmp(token, U_CONSTANT_TO_PARAM("quiche")))
{
U_DEBUG("UHTTP3::handlerNewConnection(): invalid address validation token");
U_RETURN(false);
}
token_len -= U_CONSTANT_SIZE("quiche");
const char* ptr = (const char*)&token[0] + U_CONSTANT_SIZE("quiche");
if (token_len < peer_addr_len ||
memcmp(ptr, &peer_addr, peer_addr_len))
{
U_DEBUG("UHTTP3::handlerNewConnection(): invalid address validation token");
U_RETURN(false);
}
ptr += peer_addr_len;
token_len -= peer_addr_len;
if (conn_id_len != token_len) // The token was not valid, meaning the retry failed, so drop the packet
{
U_DEBUG("UHTTP3::handlerNewConnection(): invalid address validation token");
U_RETURN(false);
}
// Reuse the source connection ID we sent in the Retry packet, instead of changing it again. Creates a new server-side connection
conn.conn = (quiche_conn*) U_SYSCALL(quiche_accept, "%p,%u,%p,%u,%p", conn_id, conn_id_len, (const uint8_t*)ptr, token_len, qconfig);
if (conn.conn == U_NULLPTR)
{
U_DEBUG("UHTTP3::handlerNewConnection(): failed to create connection");
U_RETURN(false);
}
U_RETURN(true);
}
bool UHTTP3::handlerAccept()
{
U_TRACE_NO_PARAM(0, "UHTTP3::handlerAccept()")
/*
{
peers->insert((const char*)conn_id, conn_id_len, (const UClientImage_Base*)&conn);
U_INTERNAL_ASSERT_POINTER(conn.conn)
U_INTERNAL_ASSERT_POINTER(conn.http3)
U_INTERNAL_ASSERT(UServer_Base::budp)
U_INTERNAL_ASSERT_POINTER(UServer_Base::pClientImage)
// Processes QUIC packets received from the peer
ssize_t done = U_SYSCALL(quiche_conn_recv, "%p,%p,%u", conn.conn, (uint8_t*)data, iBytesRead);
UServer_Base::pClientImage->conn = conn.conn;
UServer_Base::pClientImage->http3 = conn.http3;
conn.conn = U_NULLPTR;
conn.http3 = U_NULLPTR;
UServer_Base::pClientImage->socket->setRemoteAddressAndPort();
peers->replace((const char*)conn_id, conn_id_len, UServer_Base::pClientImage);
if (done == QUICHE_ERR_DONE)
{
U_DEBUG("UHTTP3::handlerRead(): done reading");
U_RETURN(true);
}
if (done < 0)
{
U_DEBUG("UHTTP3::handlerRead(): failed to process packet: %d", done);
U_RETURN(false);
}
U_DEBUG("UHTTP3::handlerRead(): recv %d bytes", done);
if (U_SYSCALL(quiche_conn_is_in_early_data, "%p", conn.conn) || // the connection has a pending handshake that has progressed
U_SYSCALL(quiche_conn_is_established, "%p", conn.conn)) // the connection handshake is complete
{
U_DEBUG("UHTTP3::handlerRead(): connection handshake is complete");
U_INTERNAL_ASSERT_EQUALS(conn.http3, U_NULLPTR)
// Creates a new HTTP/3 connection using the provided QUIC connection
conn.http3 = (quiche_h3_conn*) U_SYSCALL(quiche_h3_conn_new_with_transport, "%p,%p", conn.conn, http3_config);
if (conn.http3 == U_NULLPTR)
{
U_DEBUG("UHTTP3::handlerAccept(): failed to create HTTP/3 connection");
U_RETURN(false);
}
quiche_h3_event* ev;
while (true)
{
// Processes HTTP/3 data received from the peer
done = U_SYSCALL(quiche_h3_conn_poll, "%p,%p,%p", conn.http3, conn.conn, &ev);
if (done < 0) break;
switch (quiche_h3_event_type(ev))
{
case QUICHE_H3_EVENT_HEADERS:
{
// Iterates over the headers in the event. The `cb` callback will be called for each header in `ev`. `cb` should check the validity of
// pseudo-headers and headers. If `cb` returns any value other than `0`, processing will be interrupted and the value is returned to the caller
rc = U_SYSCALL(quiche_h3_event_for_each_header, "%p,%p,%p", ev, for_each_header, NULL);
if (rc != 0)
{
U_DEBUG("UHTTP3::handlerRead(): failed to process headers");
}
break;
}
case QUICHE_H3_EVENT_DATA:
{
U_DEBUG("UHTTP3::handlerRead(): got HTTP data");
break;
}
case QUICHE_H3_EVENT_FINISHED:
break;
}
U_SYSCALL_VOID(quiche_h3_event_free, "%p", ev);
}
}
while (true)
{
written = U_SYSCALL(quiche_conn_send, "%p,%p,%u", conn.conn, out, sizeof(out));
if (written == QUICHE_ERR_DONE)
{
U_DEBUG("UHTTP3::handlerRead(): done writing");
U_RETURN(false);
}
if (written < 0)
{
U_DEBUG("UHTTP3::handlerRead(): failed to create packet: %d", written);
U_RETURN(false);
}
sent = U_SYSCALL(sendto, "%d,%p,%u,%u,%p,%d", fd, out, written, 0, (struct sockaddr*)&USocket::peer_addr, USocket::peer_addr_len);
if (sent != written)
{
U_DEBUG("UHTTP3::handlerRead(): failed to send");
U_RETURN(false);
}
U_DEBUG("UHTTP3::handlerRead(): sent %u bytes", sent);
}
}
*/
}

View File

@ -824,7 +824,11 @@ U_NO_EXPORT void UHTTP::loadStaticLinkedServlet(const char* name, uint32_t len,
file_data->mime_index = U_usp;
U_NEW(UHTTP::UServletPage, file_data->ptr, UHTTP::UServletPage(name, len, U_NULLPTR, 0, runDynamicPage, runDynamicPageParam));
UHTTP::UServletPage* page;
U_NEW(UHTTP::UServletPage, page, UHTTP::UServletPage(name, len, U_NULLPTR, 0, runDynamicPage, runDynamicPageParam));
file_data->ptr = page;
U_INTERNAL_ASSERT_POINTER(vusp)

View File

@ -1,9 +1,9 @@
#! /bin/sh
# test-driver - basic testsuite driver script.
scriptversion=2013-07-13.22; # UTC
scriptversion=2018-03-07.03; # UTC
# Copyright (C) 2011-2013 Free Software Foundation, Inc.
# Copyright (C) 2011-2018 Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -16,7 +16,7 @@ scriptversion=2013-07-13.22; # UTC
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
@ -106,11 +106,14 @@ trap "st=143; $do_exit" 15
# Test script is run here.
"$@" >$log_file 2>&1
estatus=$?
if test $enable_hard_errors = no && test $estatus -eq 99; then
estatus=1
tweaked_estatus=1
else
tweaked_estatus=$estatus
fi
case $estatus:$expect_failure in
case $tweaked_estatus:$expect_failure in
0:yes) col=$red res=XPASS recheck=yes gcopy=yes;;
0:*) col=$grn res=PASS recheck=no gcopy=no;;
77:*) col=$blu res=SKIP recheck=no gcopy=yes;;
@ -119,6 +122,12 @@ case $estatus:$expect_failure in
*:*) col=$red res=FAIL recheck=yes gcopy=yes;;
esac
# Report the test outcome and exit status in the logs, so that one can
# know whether the test passed or failed simply by looking at the '.log'
# file, without the need of also peaking into the corresponding '.trs'
# file (automake bug#11814).
echo "$res $test_name (exit status: $estatus)" >>$log_file
# Report outcome to console.
echo "${col}${res}${std}: $test_name"
@ -131,9 +140,9 @@ echo ":copy-in-global-log: $gcopy" >> $trs_file
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:

View File

@ -473,6 +473,7 @@ wait_server_ready() {
if [ $? -eq 0 ]; then
break
fi
$SLEEP
done
}

View File

@ -1,13 +1,14 @@
RANDFILE = $ENV::HOME/.rnd
oid_file = /etc/openssl/.oid
#oid_file = /etc/openssl/.oid
oid_section = new_oids
[ new_oids ]
dnQualifier = 2.5.4.46
surName = 2.5.4.4
givenName = 2.5.4.42
initials = 2.5.4.43
generationQualifier = 2.5.4.44
# dnQualifier = 2.5.4.46
# surName = 2.5.4.4
# givenName = 2.5.4.42
# initials = 2.5.4.43
# generationQualifier = 2.5.4.44
[ req ]
default_bits = 4096

View File

@ -1 +1 @@
09A2
09DA

View File

@ -6,12 +6,12 @@
start_msg cspclient_rpc
#UTRACE="0 5M -1"
#UTRACE="0 5M 0"
#UOBJDUMP="0 100k 10"
#USIMERR="error.sim"
export UTRACE UOBJDUMP USIMERR
rm -rf CSP/cspserver_rpc.log CSP/CSP/DB_CA/log CSP/CSP/DB_CA/CA* \
rm -rf /tmp/cspserver_rpc.log CSP/cspserver_rpc.log CSP/CSP/DB_CA/log CSP/CSP/DB_CA/CA* \
out/userver_ssl.out err/userver_ssl.err \
CSP/trace.*userver_ssl*.[0-9]* CSP/object.*userver_ssl*.[0-9]* CSP/stack.*userver_ssl*.[0-9]* CSP/mempool.*userver_ssl*.[0-9]*
@ -52,7 +52,7 @@ rm -rf CSP/cspserver_rpc.log CSP/CSP/DB_CA/log CSP/CSP/DB_CA/CA* \
cat <<EOF >inp/webserver.cfg
userver {
LOG_FILE cspserver_rpc.log
LOG_FILE /tmp/cspserver_rpc.log
LOG_FILE_SZ 1M
DOCUMENT_ROOT CSP
PLUGIN rpc
@ -76,7 +76,8 @@ EOF
DIR_CMD="../../examples/userver"
start_prg_background userver_ssl -c inp/webserver.cfg
$SLEEP
wait_server_ready localhost 443
## ./CSP/request/run.sh > out/cspclient_rpc.out

View File

@ -1,13 +1,14 @@
RANDFILE = $ENV::HOME/.rnd
oid_file = /etc/openssl/.oid
#oid_file = /etc/openssl/.oid
oid_section = new_oids
[ new_oids ]
dnQualifier = 2.5.4.46
surName = 2.5.4.4
givenName = 2.5.4.42
initials = 2.5.4.43
generationQualifier = 2.5.4.44
# dnQualifier = 2.5.4.46
# surName = 2.5.4.4
# givenName = 2.5.4.42
# initials = 2.5.4.43
# generationQualifier = 2.5.4.44
[ req ]
default_bits = 4096

File diff suppressed because it is too large Load Diff

View File

@ -13,7 +13,7 @@ start_msg tsa_ssoap
DOC_ROOT=TSA
rm -rf $DOC_ROOT/*log \
rm -rf $DOC_ROOT/*log /tmp/*log \
out/userver_ssl.out err/userver_ssl.err \
trace.*userver_*.[0-9]* object.*userver_*.[0-9]* stack.*userver_*.[0-9]* mempool.*userver_*.[0-9]* \
$DOC_ROOT/trace.*userver_*.[0-9]* $DOC_ROOT/object.*userver_*.[0-9]* $DOC_ROOT/stack.*userver_*.[0-9]* $DOC_ROOT/mempool.*userver_*.[0-9]*
@ -64,7 +64,7 @@ cat <<EOF >inp/webserver.cfg
userver {
REQ_TIMEOUT 5
MAX_KEEP_ALIVE 256
LOG_FILE tsa_ssoap.log
LOG_FILE /tmp/tsa_ssoap.log
LOG_FILE_SZ 1M
DOCUMENT_ROOT TSA
PLUGIN "soap http"

View File

@ -11,7 +11,7 @@ rm -f tmp/usp_compile.sh.err /tmp/*.hpack.* \
/tmp/trace.*userver_*.[0-9]* /tmp/object.*userver_*.[0-9]* /tmp/stack.*userver_*.[0-9]* /tmp/mempool.*userver_*.[0-9]* \
$DOC_ROOT/trace.*userver_*.[0-9]* $DOC_ROOT/object.*userver_*.[0-9]* $DOC_ROOT/stack.*userver_*.[0-9]* $DOC_ROOT/mempool.*userver_*.[0-9]*
UTRACE="0 50M -1"
UTRACE="0 20M 0"
UTRACE_SIGNAL="0 50M 0"
UTRACE_FOLDER=/tmp
#UOBJDUMP="0 10M 100"
@ -70,11 +70,9 @@ wait_server_ready localhost 4433
sync
echo "PID = `cat /var/run/userver_udp.pid`"
$SLEEP
$SLEEP
curl -vvvv --http3 https://localhost:4433 &
$SLEEP
$SLEEP
killall userver_udp
$SLEEP
pkill userver_udp 2>/dev/null

View File

@ -16,7 +16,7 @@ start_msg web_server
DOC_ROOT=docroot
rm -f db/session.ssl* /tmp/ssl_session.txt /tmp/byterange* /tmp/soap.res /tmp/*.memusage.* /tmp/*.hpack.* \
$DOC_ROOT/webserver*.log* $DOC_ROOT/uploads/* /var/log/httpd/access_log \
/tmp/$DOC_ROOT/webserver*.log* $DOC_ROOT/webserver*.log* $DOC_ROOT/uploads/* /var/log/httpd/access_log \
out/userver_tcp.out err/userver_tcp.err web_server.err \
trace.*userver_*.[0-9]* object.*userver_*.[0-9]* stack.*userver_*.[0-9]* mempool.*userver_*.[0-9]* \
$DOC_ROOT/trace.*userver_*.[0-9]* $DOC_ROOT/object.*userver_*.[0-9]* $DOC_ROOT/stack.*userver_*.[0-9]* $DOC_ROOT/mempool.*userver_*.[0-9]*
@ -125,7 +125,7 @@ userver {
#MIN_SIZE_FOR_SENDFILE 1k
REQ_TIMEOUT 5
DOS_WHITE_LIST 127.0.0.1,10.30.0.0/16
LOG_FILE webserver$1.log
LOG_FILE /tmp/webserver$1.log
LOG_FILE_SZ 1M
LOG_MSG_SIZE -1
DOCUMENT_ROOT $DOC_ROOT

View File

@ -11,7 +11,7 @@ start_msg web_server_multiclient
DOC_ROOT=benchmark/docroot
rm -f $DOC_ROOT/web_server_multiclient.log* \
rm -f $DOC_ROOT/web_server_multiclient.log* /tmp/web_server_multiclient.log* \
out/userver_tcp.out err/userver_tcp.err err/web_server_multiclient.err \
trace.*userver_*.[0-9]* object.*userver_*.[0-9]* stack.*userver_*.[0-9]* mempool.*userver_*.[0-9]* \
$DOC_ROOT/trace.*userver_*.[0-9]* $DOC_ROOT/object.*userver_*.[0-9]* $DOC_ROOT/stack.*userver_*.[0-9]* $DOC_ROOT/mempool.*userver_*.[0-9]*
@ -31,10 +31,10 @@ userver {
PORT 8080
RUN_AS_USER apache
DOS_WHITE_LIST 127.0.0.1,10.30.0.0/16
LOG_FILE web_server_multiclient.log
LOG_FILE /tmp/web_server_multiclient.log
LOG_FILE_SZ 1M
LOG_MSG_SIZE -1
#REQ_TIMEOUT 5
REQ_TIMEOUT 5
#MAX_KEEP_ALIVE 3
PID_FILE /var/run/userver_tcp.pid
DOCUMENT_ROOT benchmark/docroot
@ -68,18 +68,20 @@ compile_usp
#VALGRIND='valgrind --leak-check=yes --track-origins=yes'
start_prg_background userver_tcp -c inp/webserver.cfg
wait_server_ready localhost 8080
wait_server_ready 127.0.0.1 8080
#netstat -tulap > /tmp/netstat.out 2>&1
#$CURL -v http://127.0.0.1:8080/1000.html > /tmp/curl.out 2>&1
#ab -k -n 2 -c 2 "http://$ADDRESS:8080/servlet/benchmarking?name=stefano" >/dev/null 2>&1
ab -k -n 100 -c 2 'http://127.0.0.1:8080/servlet/benchmarking?name=stefano' >/tmp/ab.out 2>&1
#ab -k -n 100000 -c 1000 'http://127.0.0.1:8080/servlet/benchmarking?name=stefano' >/tmp/ab.txt 2>&1
$SLEEP
$SLEEP
kill_server userver_tcp
mv err/userver_tcp.err err/web_server_multiclient.err
cat $DOC_ROOT/web_server_multiclient.log > out/web_server_multiclient.out
cp /tmp/web_server_multiclient.log out/web_server_multiclient.out
# Test against expected output
test_output_wc l web_server_multiclient

View File

@ -23,7 +23,7 @@ rm -f db/session.ssl* /tmp/ssl_session.txt /tmp/byterange* /tmp/soap.res /tmp/*.
#chmod 666 /proc/sys/net/ipv4/tcp_fin_timeout /proc/sys/net/core/somaxconn /proc/sys/net/ipv4/tcp_max_syn_backlog
UTRACE="0 20M 0"
#UTRACE="0 20M 0"
UTRACE_SIGNAL="0 50M -1"
UTRACE_FOLDER=/tmp
TMPDIR=/tmp
@ -198,8 +198,8 @@ export UMEMPOOL="136,0,60,100,250,-22,-17,-23,60"
#creat_config 1
#start_test $NCAT localhost
# webserver2
#creat_config 2
#start_test $NCAT localhost
creat_config 2
start_test $NCAT localhost
# webserverN
#creat_config N 2
#start_test $NCAT localhost

View File

@ -44,7 +44,7 @@ userver {
#PLUGIN "nocat ssi http"
PLUGIN_DIR ../../../../src/ulib/net/server/plugin/.libs
ORM_DRIVER_DIR ../../../../src/ulib/orm/driver/.libs
PREFORK_CHILD 0
PREFORK_CHILD 2
}
http {
ALIAS "[ / /index.php ]"
@ -79,12 +79,11 @@ wait_server_ready localhost 8080
ab -k -n 100 -c 2 'http://127.0.0.1:8080/servlet/benchmarking?name=stefano' >/tmp/ab.out 2>&1
#ab -k -n 100000 -c 1000 'http://127.0.0.1:8080/servlet/benchmarking?name=stefano' >/tmp/ab.txt 2>&1
$SLEEP
$SLEEP
kill_server userver_rng
mv err/userver_rng.err err/web_server_rng_multiclient.err
cat /tmp/web_server_rng_multiclient.log > out/web_server_rng_multiclient.out
cp /tmp/web_server_rng_multiclient.log out/web_server_rng_multiclient.out
# Test against expected output
test_output_wc l web_server_rng_multiclient

View File

@ -6,7 +6,7 @@
start_msg ioring
rm -rf err/ioring.err /tmp/ioring.log \
rm -rf err/ioring.err out/ioring.out /tmp/ioring.log \
trace.*ioring*.[0-9]* object.*ioring*.[0-9]* stack.*ioring*.[0-9]* mempool.*ioring*.[0-9]* \
/tmp/trace.*ioring*.[0-9]* /tmp/object.*ioring*.[0-9]* /tmp/stack.*ioring*.[0-9]* /tmp/mempool.*ioring*.[0-9]*
@ -28,7 +28,7 @@ userver {
PORT 8080
RUN_AS_USER nobody
#MIN_SIZE_FOR_SENDFILE 1k
#REQ_TIMEOUT 5
REQ_TIMEOUT 5
WELCOME_MSG "220 david.unirel.intranet LCSP server (Version 1.1.0) ready.\n"
DOS_WHITE_LIST 127.0.0.1,10.30.0.0/16
LOG_FILE /tmp/ioring.log
@ -44,8 +44,8 @@ userver {
}
http {
CACHE_FILE_MASK _off_
#ENABLE_INOTIFY yes
#REQUEST_READ_TIMEOUT 30
ENABLE_INOTIFY yes
REQUEST_READ_TIMEOUT 30
APACHE_LIKE_LOG /var/log/httpd/access_log
}
EOF
@ -57,7 +57,7 @@ start_prg_background ioring ../examples/inp/webserver.cfg
wait_server_ready localhost 8080
#../examples/sendbytes.pl
#$SLEEP
$SLEEP
send_req $NCAT localhost 8080 inp/http/form_enctype.http ioring 5 kill
#ln -s ../examples/benchmark/docroot/servlet