mirror of
https://github.com/stefanocasazza/ULib.git
synced 2025-10-05 19:18:01 +08:00
commit
18af5d8e12
2
configure
vendored
2
configure
vendored
|
@ -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='#'
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
23
test-driver
23
test-driver
|
@ -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:
|
||||
|
|
|
@ -473,6 +473,7 @@ wait_server_ready() {
|
|||
if [ $? -eq 0 ]; then
|
||||
break
|
||||
fi
|
||||
$SLEEP
|
||||
done
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1 +1 @@
|
|||
09A2
|
||||
09DA
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue
Block a user