Expand usage of macros for protocol characters.

This commit makes use of the existing PqMsg_* macros in more places
and adds new PqReplMsg_* and PqBackupMsg_* macros for use in
special replication and backup messages, respectively.

Author: Dave Cramer <davecramer@gmail.com>
Co-authored-by: Fabrízio de Royes Mello <fabriziomello@gmail.com>
Reviewed-by: Jacob Champion <jacob.champion@enterprisedb.com>
Reviewed-by: Álvaro Herrera <alvherre@kurilemu.de>
Reviewed-by: Euler Taveira <euler@eulerto.com>
Discussion: https://postgr.es/m/aIECfYfevCUpenBT@nathan
Discussion: https://postgr.es/m/CAFcNs%2Br73NOUb7%2BqKrV4HHEki02CS96Z%2Bx19WaFgE087BWwEng%40mail.gmail.com
pull/239/head
Nathan Bossart 1 month ago
parent 35baa60cc7
commit 9ea3b6f751
  1. 14
      src/backend/backup/basebackup_copy.c
  2. 4
      src/backend/replication/logical/applyparallelworker.c
  3. 10
      src/backend/replication/logical/worker.c
  4. 8
      src/backend/replication/walreceiver.c
  5. 25
      src/backend/replication/walsender.c
  6. 9
      src/bin/pg_basebackup/pg_basebackup.c
  7. 11
      src/bin/pg_basebackup/pg_recvlogical.c
  8. 11
      src/bin/pg_basebackup/receivelog.c
  9. 21
      src/include/libpq/protocol.h

@ -143,7 +143,7 @@ bbsink_copystream_begin_backup(bbsink *sink)
buf = palloc(mysink->base.bbs_buffer_length + MAXIMUM_ALIGNOF); buf = palloc(mysink->base.bbs_buffer_length + MAXIMUM_ALIGNOF);
mysink->msgbuffer = buf + (MAXIMUM_ALIGNOF - 1); mysink->msgbuffer = buf + (MAXIMUM_ALIGNOF - 1);
mysink->base.bbs_buffer = buf + MAXIMUM_ALIGNOF; mysink->base.bbs_buffer = buf + MAXIMUM_ALIGNOF;
mysink->msgbuffer[0] = 'd'; /* archive or manifest data */ mysink->msgbuffer[0] = PqMsg_CopyData; /* archive or manifest data */
/* Tell client the backup start location. */ /* Tell client the backup start location. */
SendXlogRecPtrResult(state->startptr, state->starttli); SendXlogRecPtrResult(state->startptr, state->starttli);
@ -170,7 +170,7 @@ bbsink_copystream_begin_archive(bbsink *sink, const char *archive_name)
ti = list_nth(state->tablespaces, state->tablespace_num); ti = list_nth(state->tablespaces, state->tablespace_num);
pq_beginmessage(&buf, PqMsg_CopyData); pq_beginmessage(&buf, PqMsg_CopyData);
pq_sendbyte(&buf, 'n'); /* New archive */ pq_sendbyte(&buf, PqBackupMsg_NewArchive);
pq_sendstring(&buf, archive_name); pq_sendstring(&buf, archive_name);
pq_sendstring(&buf, ti->path == NULL ? "" : ti->path); pq_sendstring(&buf, ti->path == NULL ? "" : ti->path);
pq_endmessage(&buf); pq_endmessage(&buf);
@ -191,7 +191,7 @@ bbsink_copystream_archive_contents(bbsink *sink, size_t len)
if (mysink->send_to_client) if (mysink->send_to_client)
{ {
/* Add one because we're also sending a leading type byte. */ /* Add one because we're also sending a leading type byte. */
pq_putmessage('d', mysink->msgbuffer, len + 1); pq_putmessage(PqMsg_CopyData, mysink->msgbuffer, len + 1);
} }
/* Consider whether to send a progress report to the client. */ /* Consider whether to send a progress report to the client. */
@ -221,7 +221,7 @@ bbsink_copystream_archive_contents(bbsink *sink, size_t len)
mysink->last_progress_report_time = now; mysink->last_progress_report_time = now;
pq_beginmessage(&buf, PqMsg_CopyData); pq_beginmessage(&buf, PqMsg_CopyData);
pq_sendbyte(&buf, 'p'); /* Progress report */ pq_sendbyte(&buf, PqBackupMsg_ProgressReport);
pq_sendint64(&buf, state->bytes_done); pq_sendint64(&buf, state->bytes_done);
pq_endmessage(&buf); pq_endmessage(&buf);
pq_flush_if_writable(); pq_flush_if_writable();
@ -247,7 +247,7 @@ bbsink_copystream_end_archive(bbsink *sink)
mysink->bytes_done_at_last_time_check = state->bytes_done; mysink->bytes_done_at_last_time_check = state->bytes_done;
mysink->last_progress_report_time = GetCurrentTimestamp(); mysink->last_progress_report_time = GetCurrentTimestamp();
pq_beginmessage(&buf, PqMsg_CopyData); pq_beginmessage(&buf, PqMsg_CopyData);
pq_sendbyte(&buf, 'p'); /* Progress report */ pq_sendbyte(&buf, PqBackupMsg_ProgressReport);
pq_sendint64(&buf, state->bytes_done); pq_sendint64(&buf, state->bytes_done);
pq_endmessage(&buf); pq_endmessage(&buf);
pq_flush_if_writable(); pq_flush_if_writable();
@ -262,7 +262,7 @@ bbsink_copystream_begin_manifest(bbsink *sink)
StringInfoData buf; StringInfoData buf;
pq_beginmessage(&buf, PqMsg_CopyData); pq_beginmessage(&buf, PqMsg_CopyData);
pq_sendbyte(&buf, 'm'); /* Manifest */ pq_sendbyte(&buf, PqBackupMsg_Manifest);
pq_endmessage(&buf); pq_endmessage(&buf);
} }
@ -277,7 +277,7 @@ bbsink_copystream_manifest_contents(bbsink *sink, size_t len)
if (mysink->send_to_client) if (mysink->send_to_client)
{ {
/* Add one because we're also sending a leading type byte. */ /* Add one because we're also sending a leading type byte. */
pq_putmessage('d', mysink->msgbuffer, len + 1); pq_putmessage(PqMsg_CopyData, mysink->msgbuffer, len + 1);
} }
} }

@ -778,10 +778,10 @@ LogicalParallelApplyLoop(shm_mq_handle *mqh)
/* /*
* The first byte of messages sent from leader apply worker to * The first byte of messages sent from leader apply worker to
* parallel apply workers can only be 'w'. * parallel apply workers can only be PqReplMsg_WALData.
*/ */
c = pq_getmsgbyte(&s); c = pq_getmsgbyte(&s);
if (c != 'w') if (c != PqReplMsg_WALData)
elog(ERROR, "unexpected message \"%c\"", c); elog(ERROR, "unexpected message \"%c\"", c);
/* /*

@ -3994,7 +3994,7 @@ LogicalRepApplyLoop(XLogRecPtr last_received)
c = pq_getmsgbyte(&s); c = pq_getmsgbyte(&s);
if (c == 'w') if (c == PqReplMsg_WALData)
{ {
XLogRecPtr start_lsn; XLogRecPtr start_lsn;
XLogRecPtr end_lsn; XLogRecPtr end_lsn;
@ -4016,7 +4016,7 @@ LogicalRepApplyLoop(XLogRecPtr last_received)
maybe_advance_nonremovable_xid(&rdt_data, false); maybe_advance_nonremovable_xid(&rdt_data, false);
} }
else if (c == 'k') else if (c == PqReplMsg_Keepalive)
{ {
XLogRecPtr end_lsn; XLogRecPtr end_lsn;
TimestampTz timestamp; TimestampTz timestamp;
@ -4035,7 +4035,7 @@ LogicalRepApplyLoop(XLogRecPtr last_received)
UpdateWorkerStats(last_received, timestamp, true); UpdateWorkerStats(last_received, timestamp, true);
} }
else if (c == 's') /* Primary status update */ else if (c == PqReplMsg_PrimaryStatusUpdate)
{ {
rdt_data.remote_lsn = pq_getmsgint64(&s); rdt_data.remote_lsn = pq_getmsgint64(&s);
rdt_data.remote_oldestxid = FullTransactionIdFromU64((uint64) pq_getmsgint64(&s)); rdt_data.remote_oldestxid = FullTransactionIdFromU64((uint64) pq_getmsgint64(&s));
@ -4267,7 +4267,7 @@ send_feedback(XLogRecPtr recvpos, bool force, bool requestReply)
else else
resetStringInfo(reply_message); resetStringInfo(reply_message);
pq_sendbyte(reply_message, 'r'); pq_sendbyte(reply_message, PqReplMsg_StandbyStatusUpdate);
pq_sendint64(reply_message, recvpos); /* write */ pq_sendint64(reply_message, recvpos); /* write */
pq_sendint64(reply_message, flushpos); /* flush */ pq_sendint64(reply_message, flushpos); /* flush */
pq_sendint64(reply_message, writepos); /* apply */ pq_sendint64(reply_message, writepos); /* apply */
@ -4438,7 +4438,7 @@ request_publisher_status(RetainDeadTuplesData *rdt_data)
* Send the current time to update the remote walsender's latest reply * Send the current time to update the remote walsender's latest reply
* message received time. * message received time.
*/ */
pq_sendbyte(request_message, 'p'); pq_sendbyte(request_message, PqReplMsg_PrimaryStatusRequest);
pq_sendint64(request_message, GetCurrentTimestamp()); pq_sendint64(request_message, GetCurrentTimestamp());
elog(DEBUG2, "sending publisher status request message"); elog(DEBUG2, "sending publisher status request message");

@ -826,7 +826,7 @@ XLogWalRcvProcessMsg(unsigned char type, char *buf, Size len, TimeLineID tli)
switch (type) switch (type)
{ {
case 'w': /* WAL records */ case PqReplMsg_WALData:
{ {
StringInfoData incoming_message; StringInfoData incoming_message;
@ -850,7 +850,7 @@ XLogWalRcvProcessMsg(unsigned char type, char *buf, Size len, TimeLineID tli)
XLogWalRcvWrite(buf, len, dataStart, tli); XLogWalRcvWrite(buf, len, dataStart, tli);
break; break;
} }
case 'k': /* Keepalive */ case PqReplMsg_Keepalive:
{ {
StringInfoData incoming_message; StringInfoData incoming_message;
@ -1130,7 +1130,7 @@ XLogWalRcvSendReply(bool force, bool requestReply)
applyPtr = GetXLogReplayRecPtr(NULL); applyPtr = GetXLogReplayRecPtr(NULL);
resetStringInfo(&reply_message); resetStringInfo(&reply_message);
pq_sendbyte(&reply_message, 'r'); pq_sendbyte(&reply_message, PqReplMsg_StandbyStatusUpdate);
pq_sendint64(&reply_message, writePtr); pq_sendint64(&reply_message, writePtr);
pq_sendint64(&reply_message, flushPtr); pq_sendint64(&reply_message, flushPtr);
pq_sendint64(&reply_message, applyPtr); pq_sendint64(&reply_message, applyPtr);
@ -1234,7 +1234,7 @@ XLogWalRcvSendHSFeedback(bool immed)
/* Construct the message and send it. */ /* Construct the message and send it. */
resetStringInfo(&reply_message); resetStringInfo(&reply_message);
pq_sendbyte(&reply_message, 'h'); pq_sendbyte(&reply_message, PqReplMsg_HotStandbyFeedback);
pq_sendint64(&reply_message, GetCurrentTimestamp()); pq_sendint64(&reply_message, GetCurrentTimestamp());
pq_sendint32(&reply_message, xmin); pq_sendint32(&reply_message, xmin);
pq_sendint32(&reply_message, xmin_epoch); pq_sendint32(&reply_message, xmin_epoch);

@ -1534,7 +1534,7 @@ WalSndPrepareWrite(LogicalDecodingContext *ctx, XLogRecPtr lsn, TransactionId xi
resetStringInfo(ctx->out); resetStringInfo(ctx->out);
pq_sendbyte(ctx->out, 'w'); pq_sendbyte(ctx->out, PqReplMsg_WALData);
pq_sendint64(ctx->out, lsn); /* dataStart */ pq_sendint64(ctx->out, lsn); /* dataStart */
pq_sendint64(ctx->out, lsn); /* walEnd */ pq_sendint64(ctx->out, lsn); /* walEnd */
@ -2292,7 +2292,8 @@ ProcessRepliesIfAny(void)
switch (firstchar) switch (firstchar)
{ {
/* /*
* 'd' means a standby reply wrapped in a CopyData packet. * PqMsg_CopyData means a standby reply wrapped in a CopyData
* packet.
*/ */
case PqMsg_CopyData: case PqMsg_CopyData:
ProcessStandbyMessage(); ProcessStandbyMessage();
@ -2300,8 +2301,9 @@ ProcessRepliesIfAny(void)
break; break;
/* /*
* CopyDone means the standby requested to finish streaming. * PqMsg_CopyDone means the standby requested to finish
* Reply with CopyDone, if we had not sent that already. * streaming. Reply with CopyDone, if we had not sent that
* already.
*/ */
case PqMsg_CopyDone: case PqMsg_CopyDone:
if (!streamingDoneSending) if (!streamingDoneSending)
@ -2315,7 +2317,8 @@ ProcessRepliesIfAny(void)
break; break;
/* /*
* 'X' means that the standby is closing down the socket. * PqMsg_Terminate means that the standby is closing down the
* socket.
*/ */
case PqMsg_Terminate: case PqMsg_Terminate:
proc_exit(0); proc_exit(0);
@ -2350,15 +2353,15 @@ ProcessStandbyMessage(void)
switch (msgtype) switch (msgtype)
{ {
case 'r': case PqReplMsg_StandbyStatusUpdate:
ProcessStandbyReplyMessage(); ProcessStandbyReplyMessage();
break; break;
case 'h': case PqReplMsg_HotStandbyFeedback:
ProcessStandbyHSFeedbackMessage(); ProcessStandbyHSFeedbackMessage();
break; break;
case 'p': case PqReplMsg_PrimaryStatusRequest:
ProcessStandbyPSRequestMessage(); ProcessStandbyPSRequestMessage();
break; break;
@ -2752,7 +2755,7 @@ ProcessStandbyPSRequestMessage(void)
/* construct the message... */ /* construct the message... */
resetStringInfo(&output_message); resetStringInfo(&output_message);
pq_sendbyte(&output_message, 's'); pq_sendbyte(&output_message, PqReplMsg_PrimaryStatusUpdate);
pq_sendint64(&output_message, lsn); pq_sendint64(&output_message, lsn);
pq_sendint64(&output_message, (int64) U64FromFullTransactionId(fullOldestXidInCommit)); pq_sendint64(&output_message, (int64) U64FromFullTransactionId(fullOldestXidInCommit));
pq_sendint64(&output_message, (int64) U64FromFullTransactionId(nextFullXid)); pq_sendint64(&output_message, (int64) U64FromFullTransactionId(nextFullXid));
@ -3364,7 +3367,7 @@ XLogSendPhysical(void)
* OK to read and send the slice. * OK to read and send the slice.
*/ */
resetStringInfo(&output_message); resetStringInfo(&output_message);
pq_sendbyte(&output_message, 'w'); pq_sendbyte(&output_message, PqReplMsg_WALData);
pq_sendint64(&output_message, startptr); /* dataStart */ pq_sendint64(&output_message, startptr); /* dataStart */
pq_sendint64(&output_message, SendRqstPtr); /* walEnd */ pq_sendint64(&output_message, SendRqstPtr); /* walEnd */
@ -4135,7 +4138,7 @@ WalSndKeepalive(bool requestReply, XLogRecPtr writePtr)
/* construct the message... */ /* construct the message... */
resetStringInfo(&output_message); resetStringInfo(&output_message);
pq_sendbyte(&output_message, 'k'); pq_sendbyte(&output_message, PqReplMsg_Keepalive);
pq_sendint64(&output_message, XLogRecPtrIsInvalid(writePtr) ? sentPtr : writePtr); pq_sendint64(&output_message, XLogRecPtrIsInvalid(writePtr) ? sentPtr : writePtr);
pq_sendint64(&output_message, GetCurrentTimestamp()); pq_sendint64(&output_message, GetCurrentTimestamp());
pq_sendbyte(&output_message, requestReply ? 1 : 0); pq_sendbyte(&output_message, requestReply ? 1 : 0);

@ -35,6 +35,7 @@
#include "fe_utils/option_utils.h" #include "fe_utils/option_utils.h"
#include "fe_utils/recovery_gen.h" #include "fe_utils/recovery_gen.h"
#include "getopt_long.h" #include "getopt_long.h"
#include "libpq/protocol.h"
#include "receivelog.h" #include "receivelog.h"
#include "streamutil.h" #include "streamutil.h"
@ -1338,7 +1339,7 @@ ReceiveArchiveStreamChunk(size_t r, char *copybuf, void *callback_data)
/* Each CopyData message begins with a type byte. */ /* Each CopyData message begins with a type byte. */
switch (GetCopyDataByte(r, copybuf, &cursor)) switch (GetCopyDataByte(r, copybuf, &cursor))
{ {
case 'n': case PqBackupMsg_NewArchive:
{ {
/* New archive. */ /* New archive. */
char *archive_name; char *archive_name;
@ -1410,7 +1411,7 @@ ReceiveArchiveStreamChunk(size_t r, char *copybuf, void *callback_data)
break; break;
} }
case 'd': case PqMsg_CopyData:
{ {
/* Archive or manifest data. */ /* Archive or manifest data. */
if (state->manifest_buffer != NULL) if (state->manifest_buffer != NULL)
@ -1446,7 +1447,7 @@ ReceiveArchiveStreamChunk(size_t r, char *copybuf, void *callback_data)
break; break;
} }
case 'p': case PqBackupMsg_ProgressReport:
{ {
/* /*
* Progress report. * Progress report.
@ -1465,7 +1466,7 @@ ReceiveArchiveStreamChunk(size_t r, char *copybuf, void *callback_data)
break; break;
} }
case 'm': case PqBackupMsg_Manifest:
{ {
/* /*
* Manifest data will be sent next. This message is not * Manifest data will be sent next. This message is not

@ -24,6 +24,7 @@
#include "getopt_long.h" #include "getopt_long.h"
#include "libpq-fe.h" #include "libpq-fe.h"
#include "libpq/pqsignal.h" #include "libpq/pqsignal.h"
#include "libpq/protocol.h"
#include "pqexpbuffer.h" #include "pqexpbuffer.h"
#include "streamutil.h" #include "streamutil.h"
@ -149,7 +150,7 @@ sendFeedback(PGconn *conn, TimestampTz now, bool force, bool replyRequested)
LSN_FORMAT_ARGS(output_fsync_lsn), LSN_FORMAT_ARGS(output_fsync_lsn),
replication_slot); replication_slot);
replybuf[len] = 'r'; replybuf[len] = PqReplMsg_StandbyStatusUpdate;
len += 1; len += 1;
fe_sendint64(output_written_lsn, &replybuf[len]); /* write */ fe_sendint64(output_written_lsn, &replybuf[len]); /* write */
len += 8; len += 8;
@ -454,7 +455,7 @@ StreamLogicalLog(void)
} }
/* Check the message type. */ /* Check the message type. */
if (copybuf[0] == 'k') if (copybuf[0] == PqReplMsg_Keepalive)
{ {
int pos; int pos;
bool replyRequested; bool replyRequested;
@ -466,7 +467,7 @@ StreamLogicalLog(void)
* We just check if the server requested a reply, and ignore the * We just check if the server requested a reply, and ignore the
* rest. * rest.
*/ */
pos = 1; /* skip msgtype 'k' */ pos = 1; /* skip msgtype PqReplMsg_Keepalive */
walEnd = fe_recvint64(&copybuf[pos]); walEnd = fe_recvint64(&copybuf[pos]);
output_written_lsn = Max(walEnd, output_written_lsn); output_written_lsn = Max(walEnd, output_written_lsn);
@ -509,7 +510,7 @@ StreamLogicalLog(void)
continue; continue;
} }
else if (copybuf[0] != 'w') else if (copybuf[0] != PqReplMsg_WALData)
{ {
pg_log_error("unrecognized streaming header: \"%c\"", pg_log_error("unrecognized streaming header: \"%c\"",
copybuf[0]); copybuf[0]);
@ -521,7 +522,7 @@ StreamLogicalLog(void)
* message. We only need the WAL location field (dataStart), the rest * message. We only need the WAL location field (dataStart), the rest
* of the header is ignored. * of the header is ignored.
*/ */
hdr_len = 1; /* msgtype 'w' */ hdr_len = 1; /* msgtype PqReplMsg_WALData */
hdr_len += 8; /* dataStart */ hdr_len += 8; /* dataStart */
hdr_len += 8; /* walEnd */ hdr_len += 8; /* walEnd */
hdr_len += 8; /* sendTime */ hdr_len += 8; /* sendTime */

@ -21,6 +21,7 @@
#include "access/xlog_internal.h" #include "access/xlog_internal.h"
#include "common/logging.h" #include "common/logging.h"
#include "libpq-fe.h" #include "libpq-fe.h"
#include "libpq/protocol.h"
#include "receivelog.h" #include "receivelog.h"
#include "streamutil.h" #include "streamutil.h"
@ -338,7 +339,7 @@ sendFeedback(PGconn *conn, XLogRecPtr blockpos, TimestampTz now, bool replyReque
char replybuf[1 + 8 + 8 + 8 + 8 + 1]; char replybuf[1 + 8 + 8 + 8 + 8 + 1];
int len = 0; int len = 0;
replybuf[len] = 'r'; replybuf[len] = PqReplMsg_StandbyStatusUpdate;
len += 1; len += 1;
fe_sendint64(blockpos, &replybuf[len]); /* write */ fe_sendint64(blockpos, &replybuf[len]); /* write */
len += 8; len += 8;
@ -823,13 +824,13 @@ HandleCopyStream(PGconn *conn, StreamCtl *stream,
} }
/* Check the message type. */ /* Check the message type. */
if (copybuf[0] == 'k') if (copybuf[0] == PqReplMsg_Keepalive)
{ {
if (!ProcessKeepaliveMsg(conn, stream, copybuf, r, blockpos, if (!ProcessKeepaliveMsg(conn, stream, copybuf, r, blockpos,
&last_status)) &last_status))
goto error; goto error;
} }
else if (copybuf[0] == 'w') else if (copybuf[0] == PqReplMsg_WALData)
{ {
if (!ProcessWALDataMsg(conn, stream, copybuf, r, &blockpos)) if (!ProcessWALDataMsg(conn, stream, copybuf, r, &blockpos))
goto error; goto error;
@ -1001,7 +1002,7 @@ ProcessKeepaliveMsg(PGconn *conn, StreamCtl *stream, char *copybuf, int len,
* Parse the keepalive message, enclosed in the CopyData message. We just * Parse the keepalive message, enclosed in the CopyData message. We just
* check if the server requested a reply, and ignore the rest. * check if the server requested a reply, and ignore the rest.
*/ */
pos = 1; /* skip msgtype 'k' */ pos = 1; /* skip msgtype PqReplMsg_Keepalive */
pos += 8; /* skip walEnd */ pos += 8; /* skip walEnd */
pos += 8; /* skip sendTime */ pos += 8; /* skip sendTime */
@ -1064,7 +1065,7 @@ ProcessWALDataMsg(PGconn *conn, StreamCtl *stream, char *copybuf, int len,
* message. We only need the WAL location field (dataStart), the rest of * message. We only need the WAL location field (dataStart), the rest of
* the header is ignored. * the header is ignored.
*/ */
hdr_len = 1; /* msgtype 'w' */ hdr_len = 1; /* msgtype PqReplMsg_WALData */
hdr_len += 8; /* dataStart */ hdr_len += 8; /* dataStart */
hdr_len += 8; /* walEnd */ hdr_len += 8; /* walEnd */
hdr_len += 8; /* sendTime */ hdr_len += 8; /* sendTime */

@ -69,6 +69,27 @@
#define PqMsg_Progress 'P' #define PqMsg_Progress 'P'
/* Replication codes sent by the primary (wrapped in CopyData messages). */
#define PqReplMsg_Keepalive 'k'
#define PqReplMsg_PrimaryStatusUpdate 's'
#define PqReplMsg_WALData 'w'
/* Replication codes sent by the standby (wrapped in CopyData messages). */
#define PqReplMsg_HotStandbyFeedback 'h'
#define PqReplMsg_PrimaryStatusRequest 'p'
#define PqReplMsg_StandbyStatusUpdate 'r'
/* Codes used for backups via COPY OUT (wrapped in CopyData messages). */
#define PqBackupMsg_Manifest 'm'
#define PqBackupMsg_NewArchive 'n'
#define PqBackupMsg_ProgressReport 'p'
/* These are the authentication request codes sent by the backend. */ /* These are the authentication request codes sent by the backend. */
#define AUTH_REQ_OK 0 /* User is authenticated */ #define AUTH_REQ_OK 0 /* User is authenticated */

Loading…
Cancel
Save