Skip to content

Commit 531bddb

Browse files
committed
Update Bluewing Server to build 25 (final ANSI)
Final ANSI build; adds client and channel name checks to make sure valid ASCII human-readable names are used. Added relayserver::client::istrusted(). Whether a client is being disconnected from misuse of messages, or not, is now possible to view in the Disconnect handler, even when client has not received Lacewing Connect Success response. This was necessary as connections dropped due to improper messages before On Connect was triggered may have been treated as if they got On Connect triggered. Added write lock around setting welcome message. Fixed a compilation warning when building for 64-bit. Fixed some excess whitespace.
1 parent 939b609 commit 531bddb

File tree

8 files changed

+264
-189
lines changed

8 files changed

+264
-189
lines changed

.editorconfig

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,12 @@ insert_final_newline = true
66
charset = utf-8
77
indent_style = tab
88
indent_size = 4
9-
trim_trailing_whitespace = true
9+
trim_trailing_whitespace = true
10+
11+
[*.{md}]
12+
end_of_line = lf
13+
insert_final_newline = true
14+
charset = utf-8
15+
indent_style = tab
16+
indent_size = 4
17+
trim_trailing_whitespace = false

Lacewing/Lacewing.h

Lines changed: 144 additions & 139 deletions
Large diffs are not rendered by default.

Lacewing/PhiAddress.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ bool lw_sv_cmp(std::string_view first, std::string_view second)
3535
if (first.size() != second.size())
3636
return false;
3737

38-
return !strncmp(first.data(), second.data(), first.size());
38+
return !memcmp(first.data(), second.data(), first.size());
3939
}
4040

4141
/// <summary> Compares if two strings match, returns true if so. Case insensitive. Does a size check. </summary>

Lacewing/RelayClient.cc

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ namespace lacewing
159159
std::shared_ptr<relayclient::channel> relayclientinternal::findchannelbyid(unsigned short id)
160160
{
161161
lacewing::readlock rl = this->client.lock.createReadLock();
162-
auto i = std::find_if(channels.cbegin(), channels.cend(),
162+
auto i = std::find_if(channels.cbegin(), channels.cend(),
163163
[&](const std::shared_ptr<const relayclient::channel> &c) { return c->id() == id; });
164164
return i == channels.cend() ? nullptr : *i;
165165
}
@@ -170,7 +170,7 @@ namespace lacewing
170170

171171
/* opening 0 byte */
172172
socket->write("", 1);
173-
173+
174174
// internal.udp->host(socket->server_address(), nullptr, 0U);
175175

176176
framebuilder &message = internal.message;
@@ -211,7 +211,7 @@ namespace lacewing
211211
char * dataCpy = (char *)malloc(size);
212212
if (!dataCpy)
213213
throw std::exception("Out of memory.");
214-
214+
215215
memcpy(dataCpy, data, size);
216216

217217
internal.reader.process(dataCpy, size);
@@ -364,7 +364,7 @@ namespace lacewing
364364
void relayclient::join(std::string_view channelName, bool hidden, bool autoclose)
365365
{
366366
relayclientinternal &internal = *((relayclientinternal *)internaltag);
367-
367+
368368
if (name().empty())
369369
{
370370
error error = lacewing::error_new();
@@ -541,7 +541,7 @@ namespace lacewing
541541
lacewing::readlock rl = lock.createReadLock();
542542
return _id;
543543
}
544-
544+
545545
std::string relayclient::channel::peer::name() const
546546
{
547547
lacewing::readlock rl = lock.createReadLock();
@@ -559,14 +559,14 @@ namespace lacewing
559559
// Atomic, no point changing it
560560
return _readonly;
561561
}
562-
562+
563563
size_t relayclient::channelcount() const
564564
{
565565
lacewing::readlock rl = lock.createReadLock();
566566
return ((relayclientinternal *)internaltag)->channels.size();
567567
}
568568

569-
int relayclient::id() const
569+
lw_ui16 relayclient::id() const
570570
{
571571
lacewing::readlock rl = lock.createReadLock();
572572
return ((relayclientinternal *)internaltag)->id;
@@ -587,8 +587,8 @@ namespace lacewing
587587

588588
bool relayclientinternal::messagehandler(unsigned char type, const char * message, size_t size, bool blasted)
589589
{
590-
unsigned char messagetypeid = (type >> 4);
591-
unsigned char variant = (type << 4);
590+
lw_ui8 messagetypeid = (type >> 4);
591+
lw_ui8 variant = (type << 4);
592592

593593
variant >>= 4;
594594

@@ -598,8 +598,8 @@ namespace lacewing
598598
{
599599
case 0: /* response */
600600
{
601-
unsigned char responsetype = reader.get <unsigned char>();
602-
bool succeeded = reader.get <unsigned char>() != 0;
601+
lw_ui8 responsetype = reader.get <lw_ui8>();
602+
bool succeeded = reader.get <lw_ui8>() != 0;
603603

604604
if (reader.failed)
605605
break;
@@ -610,14 +610,14 @@ namespace lacewing
610610
{
611611
if (succeeded)
612612
{
613-
id = reader.get <unsigned short>();
613+
id = reader.get <lw_ui16>();
614614

615615
// Don't expect welcome message to be null terminated
616616
std::string_view welcomemessage = reader.get(reader.bytesleft());
617617

618618
if (reader.failed)
619619
break;
620-
620+
621621
this->welcomemessage = welcomemessage;
622622

623623
socket->server_address()->resolve();
@@ -712,16 +712,16 @@ namespace lacewing
712712

713713
auto channel = std::make_shared<relayclient::channel>(*this);
714714
auto channelWriteLock = channel->lock.createWriteLock();
715-
715+
716716
channel->_id = channelid;
717717
channel->_name = name;
718718
channel->_ischannelmaster = (flags & 1) != 0;
719719

720720
for (; reader.bytesleft() > 0;)
721721
{
722-
int peerid = reader.get <unsigned short>();
723-
int flags2 = reader.get <unsigned char>();
724-
int namelength2 = reader.get <unsigned char>();
722+
lw_ui16 peerid = reader.get <lw_ui16>();
723+
lw_ui8 flags2 = reader.get <lw_ui8>();
724+
lw_ui8 namelength2 = reader.get <lw_ui8>();
725725
std::string_view name2 = reader.get(namelength2);
726726

727727
if (reader.failed)
@@ -781,7 +781,7 @@ namespace lacewing
781781

782782
if (handler_channel_leave)
783783
handler_channel_leave(client, channel);
784-
784+
785785
// Handler BEFORE finding it in channel list, in case leave handler calls disconnect.
786786
if (!connected)
787787
break;
@@ -953,8 +953,8 @@ namespace lacewing
953953

954954
case 4: /* binaryserverchannelmessage */
955955
{
956-
int subchannel = reader.get <unsigned char>();
957-
unsigned short channel = reader.get<unsigned short>();
956+
lw_ui8 subchannel = reader.get <lw_ui8>();
957+
lw_ui16 channel = reader.get<lw_ui16>();
958958
if (reader.failed)
959959
break;
960960

@@ -1033,7 +1033,7 @@ namespace lacewing
10331033

10341034
lw_ui8 flags = reader.get <lw_ui8>();
10351035
std::string_view name = reader.get(reader.bytesleft()); // name's not null terminated
1036-
1036+
10371037
if (reader.failed)
10381038
{
10391039
/* no flags/name - the peer must have left the channel */
@@ -1044,9 +1044,12 @@ namespace lacewing
10441044
return true;
10451045

10461046
peer->_readonly = true;
1047+
1048+
channelWriteLock.lw_unlock(); // Don't leave it locked while handler is run
1049+
10471050
if (handler_peer_disconnect)
10481051
handler_peer_disconnect(client, channel2, peer);
1049-
1052+
10501053
channel2 = findchannelbyid(channel);
10511054

10521055
// Handler called disconnect, so channel is no longer accessible
@@ -1055,6 +1058,7 @@ namespace lacewing
10551058

10561059
// LW_ESCALATION_NOTE
10571060
// auto channelWriteLock = channelReadLock.lw_upgrade();
1061+
channelWriteLock.lw_relock();
10581062
auto i = std::find_if(channel2->peers.begin(), channel2->peers.end(),
10591063
[=](std::shared_ptr<relayclient::channel::peer> &p) { return p->_id == peerid; });
10601064
if (i != channel2->peers.end())
@@ -1074,6 +1078,8 @@ namespace lacewing
10741078

10751079
// this does channel2->peers.push_back()
10761080
peer = channel2->addnewpeer(peerid, flags, name);
1081+
1082+
channelWriteLock.lw_unlock(); // Don't leave it locked while handler is run (when escalation happens, it will unlock by {}s
10771083
}
10781084

10791085
if (handler_peer_connect)
@@ -1244,8 +1250,8 @@ namespace lacewing
12441250
// udphellotick just sends UDPHello every 0.5s, and is managed by the relayclientinternal::udphellotimer var.
12451251
// It starts from the time the Connect Request Success message is sent.
12461252
if (!udp->hosting())
1247-
throw std::exception("udphellotick() called, but not hosting UDP.");
1248-
1253+
throw std::exception("udphellotick() called, but not hosting UDP.");
1254+
12491255
message.addheader(7, 0, true, id); /* udphello */
12501256
message.send(udp, socket->server_address());
12511257
}
@@ -1336,7 +1342,7 @@ namespace lacewing
13361342
return _ischannelmaster;
13371343
}
13381344

1339-
unsigned short relayclient::channel::peer::id() const
1345+
lw_ui16 relayclient::channel::peer::id() const
13401346
{
13411347
// We won't check for read lock, as ID cannot change, so there's no use to threadsafe-ing its access.
13421348
return _id;
@@ -1374,7 +1380,7 @@ namespace lacewing
13741380
{
13751381
relayclientinternal::channel &internal = *(relayclientinternal::channel *)internaltag;
13761382
auto end = internal.client.channels.end();
1377-
1383+
13781384
auto i = std::find_if(internal.client.channels.begin(), end,
13791385
[&](relayclientinternal::channel * &c) { return c->id == internal.id; });
13801386
return (i == end || ++i == end) ? nullptr : &(*i)->public_;
@@ -1385,7 +1391,7 @@ namespace lacewing
13851391
std::vector<relayclientinternal::channel *> &c = ((lacewing::relayclientinternal *)internaltag)->channels;
13861392
return (c.begin() == c.end()) ? nullptr : &(*c.begin())->public_;
13871393
}
1388-
1394+
13891395
relayclient::channel::peer * relayclient::channel::firstpeer() const
13901396
{
13911397
std::vector<relayclientinternal::peer *> &p = ((lacewing::relayclientinternal::channel *)internaltag)->peers;
@@ -1414,7 +1420,7 @@ namespace lacewing
14141420
lock.checkHoldsRead();
14151421
return ((relayclientinternal *)internaltag)->channellist;
14161422
}
1417-
1423+
14181424
#define autohandlerfunctions(pub, intern, handlername) \
14191425
void pub::on##handlername(pub::handler_##handlername handler) \
14201426
{ ((intern *) internaltag)->handler_##handlername = handler; \

Lacewing/RelayServer.cc

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ struct relayserverinternal
158158
decltype(msElapsedTCP) msElapsedUDP = 0;
159159
if (!client->pseudoUDP)
160160
msElapsedUDP = std::chrono::duration_cast<std::chrono::milliseconds>(currentTime - client->lastudpmessagetime).count();
161-
161+
162162
// detect a buggy version of std::chrono::steady_clock (was in a VS 2019 preview)
163163
if (msElapsedTCP < 0 || msElapsedUDP < 0 || msElapsedNonPing < 0)
164164
DebugBreak();
@@ -1356,8 +1356,8 @@ bool relayserverinternal::client_messagehandler(std::shared_ptr<relayserver::cli
13561356
{
13571357
auto cliReadLock = client->lock.createReadLock();
13581358

1359-
unsigned char messagetypeid = (type >> 4);
1360-
unsigned char variant = (type << 4);
1359+
lw_ui8 messagetypeid = (type >> 4);
1360+
lw_ui8 variant = (type << 4);
13611361

13621362
variant >>= 4;
13631363
const char * message = messageP.data();
@@ -1405,7 +1405,7 @@ bool relayserverinternal::client_messagehandler(std::shared_ptr<relayserver::cli
14051405
client->lasttcpmessagetime = ::std::chrono::steady_clock::now();
14061406

14071407
std::stringstream errStr;
1408-
bool trustedClient = true;
1408+
bool& trustedClient = client->trustedClient;
14091409

14101410
switch (messagetypeid)
14111411
{
@@ -2170,6 +2170,7 @@ std::vector<std::shared_ptr<lacewing::relayserver::client>>& relayserver::channe
21702170

21712171
void relayserver::setwelcomemessage(std::string_view message)
21722172
{
2173+
lacewing::writelock wl = lock.createWriteLock();
21732174
relayserverinternal& serverinternal = *(relayserverinternal *)internaltag;
21742175
serverinternal.welcomemessage = message;
21752176
}
@@ -2218,6 +2219,10 @@ bool relayserver::client::readonly() const
22182219
{
22192220
return _readonly;
22202221
}
2222+
bool relayserver::client::istrusted() const
2223+
{
2224+
return trustedClient;
2225+
}
22212226

22222227
std::vector<std::shared_ptr<lacewing::relayserver::channel>> & relayserver::client::getchannels()
22232228
{
@@ -2294,15 +2299,26 @@ relayserver::client::~client() noexcept(false)
22942299

22952300
std::shared_ptr<relayserver::channel> relayserver::createchannel(std::string_view channelName, std::shared_ptr<relayserver::client> master, bool hidden, bool autoclose)
22962301
{
2297-
auto channel = std::make_shared<relayserver::channel>(*(lacewing::relayserverinternal *)internaltag, channelName);
2302+
auto& serverinternal = *(lacewing::relayserverinternal *)internaltag;
2303+
auto channel = std::make_shared<relayserver::channel>(serverinternal, channelName);
22982304
auto channelWriteLock = channel->lock.createWriteLock();
22992305

23002306
channel->_channelmaster = master;
23012307
channel->_hidden = hidden;
23022308
channel->_autoclose = autoclose;
23032309

2304-
joinchannel_response(channel, master, std::string_view());
2305-
// calls serverinternal.channels.push_back(channel);
2310+
if (master)
2311+
{
2312+
joinchannel_response(channel, master, std::string_view());
2313+
// calls serverinternal.channels.push_back(channel);
2314+
}
2315+
else
2316+
{
2317+
lacewing::writelock serverWriteLock = lock.createWriteLock();
2318+
if (std::find(serverinternal.channels.cbegin(), serverinternal.channels.cend(), channel) == serverinternal.channels.cend())
2319+
serverinternal.channels.push_back(channel);
2320+
}
2321+
23062322
channelWriteLock.lw_unlock();
23072323

23082324
return channel;

Lacewing/src/windows/fdstream.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ static void completion (void * tag, OVERLAPPED * _overlapped,
8787

8888
if (error || !bytes_transferred)
8989
{
90-
9190
// First, establish if connection has died, or temporarily had an error.
9291
// If it's died, we'll do an immediate shutdown, otherwise a graceful.
9392

@@ -99,17 +98,17 @@ static void completion (void * tag, OVERLAPPED * _overlapped,
9998
// Local network went down (something providing connectivity failed)
10099
error == WSAENETDOWN ||
101100
// Local network unreachable (no route to other side)
102-
error == WSAENETUNREACH ||
101+
error == WSAENETUNREACH || error == ERROR_NETWORK_UNREACHABLE ||
103102
// Local network was reset, and this connection was closed forcibly; e.g. network adapter reset
104103
error == WSAENETRESET ||
104+
// Local or remote end aborted their connection
105+
error == WSAECONNABORTED || error == ERROR_CONNECTION_ABORTED ||
105106
// Remote end reset their connection
106-
error == WSAECONNABORTED ||
107-
// Remote end reset their connection
108-
error == WSAECONNRESET ||
109-
// Local socket was shut down via shutdown()/closesocket() call
107+
error == WSAECONNRESET || error == ERROR_CONNECTION_UNAVAIL ||
108+
// Local socket was shut down via shutdown()/closesocket() call (can also cause connection aborted)
110109
error == WSAESHUTDOWN ||
111110
// Local socket not connected
112-
error == WSAENOTCONN;
111+
error == WSAENOTCONN || error == ERROR_PORT_UNREACHABLE;
113112
lwp_trace("Closing stream %p, due to error %i. Unreachable: %s.\n", ctx, error, otherEndUnreachable ? "YES" : "NO");
114113

115114
lw_stream_close ((lw_stream) ctx, otherEndUnreachable);

Lacewing/src/windows/timer.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ lw_timer lw_timer_new (lw_pump pump)
5656
return 0;
5757

5858
ctx->pump = pump;
59-
59+
6060
ctx->shutdown_event = CreateEvent (0, TRUE, FALSE, 0);
6161
ctx->timer_handle = CreateWaitableTimer (0, FALSE, 0);
6262

@@ -112,7 +112,7 @@ void lw_timer_start (lw_timer ctx, long interval)
112112
lw_timer_stop (ctx);
113113

114114
LARGE_INTEGER due_time;
115-
due_time.QuadPart = 0 - (interval * 1000 * 10);
115+
due_time.QuadPart = 0LL - (interval * 1000LL * 10LL);
116116

117117
if (!SetWaitableTimer (ctx->timer_handle, &due_time, interval, 0, 0, 0))
118118
{

0 commit comments

Comments
 (0)