initial commit
This commit is contained in:
commit
8c8158ad5b
7 changed files with 724 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
prezzyd
|
||||
prezzyc
|
||||
*.o
|
25
Makefile
Normal file
25
Makefile
Normal file
|
@ -0,0 +1,25 @@
|
|||
CC = cc
|
||||
CFLAGS = -std=c99 -O2 -pedantic -Wall -Wextra
|
||||
LDFLAGS = -ldiscord-rpc
|
||||
OBJS = prezzyipc.o
|
||||
|
||||
all: prezzyd prezzyc
|
||||
|
||||
prezzyd: prezzyd.o ${OBJS}
|
||||
cc ${CFLAGS} -o $@ prezzyd.o ${OBJS} ${LDFLAGS}
|
||||
prezzyc: prezzyc.o ${OBJS}
|
||||
cc ${CFLAGS} -o $@ prezzyc.o ${OBJS} ${LDFLAGS}
|
||||
|
||||
.SUFFIXES: .c .o
|
||||
|
||||
.c.o:
|
||||
${CC} ${CFLAGS} -DBUILD_DATE=\"$$(date -I)\" -c $<
|
||||
|
||||
clean:
|
||||
rm -f prezzyd prezzyc prezzyd.o prezzyc.o ${OBJS}
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
prezzyd.o: prezzyd.c prezzyipc.h discord_rpc.h
|
||||
prezzyc.o: prezzyc.c prezzyipc.h
|
||||
prezzyipc.o: prezzyipc.c prezzyipc.h
|
87
discord_rpc.h
Normal file
87
discord_rpc.h
Normal file
|
@ -0,0 +1,87 @@
|
|||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
// clang-format off
|
||||
|
||||
#if defined(DISCORD_DYNAMIC_LIB)
|
||||
# if defined(_WIN32)
|
||||
# if defined(DISCORD_BUILDING_SDK)
|
||||
# define DISCORD_EXPORT __declspec(dllexport)
|
||||
# else
|
||||
# define DISCORD_EXPORT __declspec(dllimport)
|
||||
# endif
|
||||
# else
|
||||
# define DISCORD_EXPORT __attribute__((visibility("default")))
|
||||
# endif
|
||||
#else
|
||||
# define DISCORD_EXPORT
|
||||
#endif
|
||||
|
||||
// clang-format on
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct DiscordRichPresence {
|
||||
const char* state; /* max 128 bytes */
|
||||
const char* details; /* max 128 bytes */
|
||||
int64_t startTimestamp;
|
||||
int64_t endTimestamp;
|
||||
const char* largeImageKey; /* max 32 bytes */
|
||||
const char* largeImageText; /* max 128 bytes */
|
||||
const char* smallImageKey; /* max 32 bytes */
|
||||
const char* smallImageText; /* max 128 bytes */
|
||||
const char* partyId; /* max 128 bytes */
|
||||
int partySize;
|
||||
int partyMax;
|
||||
const char* matchSecret; /* max 128 bytes */
|
||||
const char* joinSecret; /* max 128 bytes */
|
||||
const char* spectateSecret; /* max 128 bytes */
|
||||
int8_t instance;
|
||||
} DiscordRichPresence;
|
||||
|
||||
typedef struct DiscordUser {
|
||||
const char* userId;
|
||||
const char* username;
|
||||
const char* discriminator;
|
||||
const char* avatar;
|
||||
} DiscordUser;
|
||||
|
||||
typedef struct DiscordEventHandlers {
|
||||
void (*ready)(const DiscordUser* request);
|
||||
void (*disconnected)(int errorCode, const char* message);
|
||||
void (*errored)(int errorCode, const char* message);
|
||||
void (*joinGame)(const char* joinSecret);
|
||||
void (*spectateGame)(const char* spectateSecret);
|
||||
void (*joinRequest)(const DiscordUser* request);
|
||||
} DiscordEventHandlers;
|
||||
|
||||
#define DISCORD_REPLY_NO 0
|
||||
#define DISCORD_REPLY_YES 1
|
||||
#define DISCORD_REPLY_IGNORE 2
|
||||
|
||||
DISCORD_EXPORT void Discord_Initialize(const char* applicationId,
|
||||
DiscordEventHandlers* handlers,
|
||||
int autoRegister,
|
||||
const char* optionalSteamId);
|
||||
DISCORD_EXPORT void Discord_Shutdown(void);
|
||||
|
||||
/* checks for incoming messages, dispatches callbacks */
|
||||
DISCORD_EXPORT void Discord_RunCallbacks(void);
|
||||
|
||||
/* If you disable the lib starting its own io thread, you'll need to call this from your own */
|
||||
#ifdef DISCORD_DISABLE_IO_THREAD
|
||||
DISCORD_EXPORT void Discord_UpdateConnection(void);
|
||||
#endif
|
||||
|
||||
DISCORD_EXPORT void Discord_UpdatePresence(const DiscordRichPresence* presence);
|
||||
DISCORD_EXPORT void Discord_ClearPresence(void);
|
||||
|
||||
DISCORD_EXPORT void Discord_Respond(const char* userid, /* DISCORD_REPLY_ */ int reply);
|
||||
|
||||
DISCORD_EXPORT void Discord_UpdateHandlers(DiscordEventHandlers* handlers);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
146
prezzyc.c
Normal file
146
prezzyc.c
Normal file
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
* prezzyc
|
||||
* Copyright (c) 2024 Jeremy Baxter.
|
||||
*/
|
||||
|
||||
#define _PREZZYC_C_
|
||||
#define _DEFAULT_SOURCE
|
||||
|
||||
#ifndef BUILD_DATE
|
||||
#define BUILD_DATE "1970-01-01"
|
||||
#endif
|
||||
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "prezzyipc.h"
|
||||
#include "discord_rpc.h"
|
||||
|
||||
static PrezzyIpcPacket **packets;
|
||||
static int packetCount;
|
||||
|
||||
void
|
||||
addPacket(PrezzyProperty property, PrezzyPayloadType type,
|
||||
char *pString, int64_t pInteger)
|
||||
{
|
||||
PrezzyIpcPacket *p;
|
||||
size_t len;
|
||||
|
||||
p = malloc(sizeof(PrezzyIpcPacket));
|
||||
p->property = property;
|
||||
p->type = type;
|
||||
if (type == PLT_STRING) {
|
||||
len = strlen(pString) + 1;
|
||||
p->pString = malloc(len * sizeof(char));
|
||||
strbcpy(p->pString, pString, len);
|
||||
} else
|
||||
p->pInteger = pInteger;
|
||||
|
||||
packetCount++;
|
||||
packets = realloc(packets,
|
||||
packetCount * sizeof(PrezzyIpcPacket *));
|
||||
packets[packetCount - 1] = p;
|
||||
}
|
||||
|
||||
int
|
||||
getServer(const char *socketPath)
|
||||
{
|
||||
struct sockaddr_un addr;
|
||||
int fd;
|
||||
|
||||
memset(&addr, 0, sizeof(struct sockaddr_un));
|
||||
addr.sun_family = AF_UNIX;
|
||||
strbcpy(addr.sun_path, socketPath, sizeof(addr.sun_path) - 1);
|
||||
|
||||
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
|
||||
err(1, "failed to create IPC client socket");
|
||||
if (connect(fd, (struct sockaddr *)&addr,
|
||||
sizeof(struct sockaddr_un)) == -1)
|
||||
err(1, "failed to establish connection to IPC daemon");
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
fputs(
|
||||
"usage: prezzyc [-aV] [-d details] [-I icon] [-i tooltip]\n"
|
||||
" [-L large-image] [-l tooltip] [-s state]\n"
|
||||
" [-P limit] [-p size] [-T end] [-t start]\n",
|
||||
stderr);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char *buffer;
|
||||
ssize_t sz;
|
||||
int ch, i;
|
||||
int server;
|
||||
|
||||
if (argc < 2) { /* no options? */
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
while ((ch = getopt(argc, argv, "ad:I:i:L:l:P:p:s:T:t:V")) != -1) {
|
||||
switch (ch) {
|
||||
case 'a': addPacket(PREZZY_TIMESTAMP_START, PLT_INT64, NULL, time(NULL)); break;
|
||||
case 'd': addPacket(PREZZY_DETAILS, PLT_STRING, optarg, 0); break;
|
||||
case 'I': addPacket(PREZZY_ICON, PLT_STRING, optarg, 0); break;
|
||||
case 'i': addPacket(PREZZY_ICON_TOOLTIP, PLT_STRING, optarg, 0); break;
|
||||
case 'L': addPacket(PREZZY_LARGE_IMAGE, PLT_STRING, optarg, 0); break;
|
||||
case 'l': addPacket(PREZZY_LARGE_TOOLTIP, PLT_STRING, optarg, 0); break;
|
||||
case 's': addPacket(PREZZY_STATE, PLT_STRING, optarg, 0); break;
|
||||
case 'P': addPacket(PREZZY_PARTY_LIMIT, PLT_INT, NULL,
|
||||
squashLong(strtol(optarg, NULL, 10))); break;
|
||||
case 'p': addPacket(PREZZY_PARTY_SIZE, PLT_INT, NULL,
|
||||
squashLong(strtol(optarg, NULL, 10))); break;
|
||||
case 'T': addPacket(PREZZY_TIMESTAMP_END, PLT_INT64, NULL,
|
||||
strtol(optarg, NULL, 10)); break;
|
||||
case 't': addPacket(PREZZY_TIMESTAMP_START, PLT_INT64, NULL,
|
||||
strtol(optarg, NULL, 10)); break;
|
||||
case 'V':
|
||||
printf("prezzyc version 0.1 built on " BUILD_DATE "\n");
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc - optind > 0) { /* extra arguments? */
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
server = getServer(PREZZY_SOCK);
|
||||
|
||||
for (i = 0; i < packetCount; i++) {
|
||||
buffer = fromIpcPacket(*packets[i]);
|
||||
write(server, buffer, strlen(buffer));
|
||||
free(buffer);
|
||||
}
|
||||
write(server, "\0", 1);
|
||||
|
||||
buffer = malloc(PREZZY_PACKET_MAX * sizeof(char));
|
||||
memset(buffer, 0, PREZZY_PACKET_MAX);
|
||||
while ((sz = read(server, buffer, PREZZY_PACKET_MAX - 1)) > 0) {
|
||||
if (buffer[0] != 0)
|
||||
errx(1, "IPC error %d: %s", buffer[0], buffer + 1);
|
||||
}
|
||||
|
||||
if (sz == -1)
|
||||
err(1, "failed to read from IPC server");
|
||||
|
||||
for (i = 0; i < packetCount; i++) {
|
||||
if (packets[i]->type == PLT_STRING)
|
||||
free(packets[i]->pString);
|
||||
free(packets[i]);
|
||||
}
|
||||
free(packets);
|
||||
|
||||
return 0;
|
||||
}
|
258
prezzyd.c
Normal file
258
prezzyd.c
Normal file
|
@ -0,0 +1,258 @@
|
|||
/*
|
||||
* prezzyd
|
||||
* Copyright (c) 2024 Jeremy Baxter.
|
||||
*/
|
||||
|
||||
#define _PREZZYD_C_
|
||||
#define _DEFAULT_SOURCE
|
||||
|
||||
#ifndef BUILD_DATE
|
||||
#define BUILD_DATE "1970-01-01"
|
||||
#endif
|
||||
|
||||
#include <err.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "prezzyipc.h"
|
||||
#include "discord_rpc.h"
|
||||
|
||||
void
|
||||
connectHandler(const DiscordUser *user)
|
||||
{
|
||||
warnx("established connection to Discord (%s/%s)",
|
||||
user->username, user->userId);
|
||||
}
|
||||
|
||||
void
|
||||
disconnectHandler(int code, const char *message)
|
||||
{
|
||||
warnx("disconnected from client (%d: %s)", code, message);
|
||||
}
|
||||
|
||||
void
|
||||
errorHandler(int code, const char *message)
|
||||
{
|
||||
errx(1, "rpc error %d: %s", code, message);
|
||||
}
|
||||
|
||||
int
|
||||
canReadFrom(int fd)
|
||||
{
|
||||
struct pollfd *p;
|
||||
int ret;
|
||||
|
||||
p = malloc(sizeof(struct pollfd));
|
||||
p->fd = fd;
|
||||
p->events = POLLIN;
|
||||
|
||||
if (poll(p, 1, 5000) == -1)
|
||||
err(1, "failed to poll client");
|
||||
|
||||
ret = p->revents & POLLIN;
|
||||
free(p);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
ipcClose(int fd, byte code, const char *message)
|
||||
{
|
||||
write(fd, (char []){code}, 1);
|
||||
write(fd, message, strlen(message));
|
||||
if (close(fd) == -1)
|
||||
err(1, "failed to close IPC connection");
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
void
|
||||
ipcSucceed(int fd)
|
||||
{
|
||||
ipcClose(fd, 0, "OK");
|
||||
}
|
||||
|
||||
int
|
||||
makeIpcServer(const char *bindPath, int backlog)
|
||||
{
|
||||
struct sockaddr_un addr;
|
||||
int fd;
|
||||
|
||||
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
|
||||
err(1, "failed to create IPC socket");
|
||||
|
||||
if (remove(bindPath) == -1) {
|
||||
if (errno != ENOENT)
|
||||
err(1, "could not remove %s", bindPath);
|
||||
}
|
||||
|
||||
memset(&addr, 0, sizeof(struct sockaddr_un));
|
||||
addr.sun_family = AF_UNIX;
|
||||
strbcpy(addr.sun_path, bindPath, sizeof(addr.sun_path) - 1);
|
||||
|
||||
if (bind(fd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un)) == -1)
|
||||
err(1, "failed to bind to %s", bindPath);
|
||||
if (listen(fd, backlog) == -1)
|
||||
err(1, "failed to listen on IPC socket %s", bindPath);
|
||||
|
||||
if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK) == -1)
|
||||
err(1, "failed to create non-blocking IPC socket");
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
void *propertyMapping[PREZZY_PROPERTY_MAX];
|
||||
DiscordRichPresence presence;
|
||||
DiscordEventHandlers handlers;
|
||||
const char *clientId;
|
||||
int ch, sd;
|
||||
|
||||
while ((ch = getopt(argc, argv, "V")) != -1) {
|
||||
switch (ch) {
|
||||
case 'V':
|
||||
printf("prezzyd version 0.1 built on " BUILD_DATE "\n");
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc - optind != 1) {
|
||||
fputs("usage: prezzyd [-V] client-id\n", stderr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
clientId = argv[optind];
|
||||
|
||||
memset(&presence, 0, sizeof(DiscordRichPresence));
|
||||
memset(&handlers, 0, sizeof(DiscordEventHandlers));
|
||||
handlers.ready = connectHandler;
|
||||
handlers.disconnected = disconnectHandler;
|
||||
handlers.errored = errorHandler;
|
||||
|
||||
Discord_Initialize(clientId, &handlers, 1, NULL);
|
||||
|
||||
propertyMapping[PREZZY_STATE] = &presence.state;
|
||||
propertyMapping[PREZZY_DETAILS] = &presence.details;
|
||||
propertyMapping[PREZZY_LARGE_IMAGE] = &presence.largeImageKey;
|
||||
propertyMapping[PREZZY_LARGE_TOOLTIP] = &presence.largeImageText;
|
||||
propertyMapping[PREZZY_ICON] = &presence.smallImageKey;
|
||||
propertyMapping[PREZZY_ICON_TOOLTIP] = &presence.smallImageText;
|
||||
propertyMapping[PREZZY_PARTY_SIZE] = &presence.partySize;
|
||||
propertyMapping[PREZZY_PARTY_LIMIT] = &presence.partyMax;
|
||||
propertyMapping[PREZZY_TIMESTAMP_START] = &presence.startTimestamp;
|
||||
propertyMapping[PREZZY_TIMESTAMP_END] = &presence.endTimestamp;
|
||||
|
||||
/* start ipc server */
|
||||
sd = makeIpcServer(PREZZY_SOCK, 8);
|
||||
|
||||
for (;;) {
|
||||
PrezzyIpcPacket **packets;
|
||||
char buffer[PREZZY_PACKET_MAX];
|
||||
ssize_t sz;
|
||||
int client, i, packetCount;
|
||||
char ch;
|
||||
|
||||
packets = NULL;
|
||||
packetCount = 0;
|
||||
client = accept(sd, NULL, NULL);
|
||||
|
||||
if (client == -1) {
|
||||
switch (errno) {
|
||||
case EWOULDBLOCK:
|
||||
goto update;
|
||||
default:
|
||||
err(1, "failed to accept incoming IPC connection");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* IPC error codes:
|
||||
* 1: error during initial read
|
||||
* 2: bad request format
|
||||
*/
|
||||
|
||||
if (!canReadFrom(client))
|
||||
ipcClose(client, 1, "Timed out");
|
||||
|
||||
for (i = 0; (sz = read(client, &ch, 1)) > 0; i++) {
|
||||
if (i == PREZZY_PACKET_MAX) {
|
||||
ipcClose(client, 0, "OK (truncated)");
|
||||
buffer[i - 1] = '\0';
|
||||
break;
|
||||
}
|
||||
|
||||
switch (ch) {
|
||||
case '\n':
|
||||
case '\0':
|
||||
/* end current packet */
|
||||
if (i + 1 < 2 && /* are we before the payload? */
|
||||
/* accept null bytes after newlines */
|
||||
!(ch == '\0' && i == 0)) {
|
||||
ipcClose(client, 2, "Request missing payload");
|
||||
goto update;
|
||||
}
|
||||
if (buffer[0] < 0 || buffer[0] >= PREZZY_PROPERTY_MAX) {
|
||||
ipcClose(client, 2, "Invalid property byte");
|
||||
goto update;
|
||||
}
|
||||
buffer[i] = '\0';
|
||||
|
||||
packetCount++;
|
||||
packets = realloc(packets, packetCount *
|
||||
sizeof(PrezzyIpcPacket *));
|
||||
packets[packetCount - 1] = makeIpcPacket(buffer);
|
||||
|
||||
if (ch == '\0') {
|
||||
ipcSucceed(client);
|
||||
goto process;
|
||||
}
|
||||
/* '\n'; more requests later */
|
||||
i = -1;
|
||||
continue;
|
||||
default:
|
||||
buffer[i] = ch;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (sz == -1)
|
||||
err(1, "failed to read from IPC client");
|
||||
|
||||
process:
|
||||
for (i = 0; i < packetCount; i++) {
|
||||
size_t len;
|
||||
|
||||
if (packets[i]->type == PLT_STRING) {
|
||||
len = strlen(packets[i]->pString) + 1;
|
||||
*(char **)propertyMapping[packets[i]->property] =
|
||||
malloc(len * sizeof(char));
|
||||
strlcpy(*(char **)propertyMapping[packets[i]->property],
|
||||
packets[i]->pString, len);
|
||||
} else {
|
||||
if (packets[i]->type == PLT_INT64) {
|
||||
*(int64_t *)propertyMapping[packets[i]->property] =
|
||||
packets[i]->pInteger;
|
||||
} else {
|
||||
*(int *)propertyMapping[packets[i]->property] =
|
||||
squashLong(packets[i]->pInteger);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update:
|
||||
Discord_UpdatePresence(&presence);
|
||||
Discord_RunCallbacks();
|
||||
usleep(64000);
|
||||
}
|
||||
|
||||
Discord_Shutdown();
|
||||
|
||||
return 0;
|
||||
}
|
132
prezzyipc.c
Normal file
132
prezzyipc.c
Normal file
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* prezzyipc.c
|
||||
* Copyright (c) 2024 Jeremy Baxter.
|
||||
*/
|
||||
|
||||
#define _PREZZYIPC_C_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "prezzyipc.h"
|
||||
|
||||
void
|
||||
dumpPacket(PrezzyIpcPacket p)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"[packet]\n"
|
||||
"property = %d\n"
|
||||
"type = %d\n"
|
||||
"payload = ",
|
||||
p.property, p.type);
|
||||
if (p.type == PLT_STRING)
|
||||
fprintf(stderr, "%s\n", p.pString);
|
||||
else
|
||||
fprintf(stderr, "%ld\n", p.pInteger);
|
||||
}
|
||||
|
||||
char *
|
||||
fromIpcPacket(PrezzyIpcPacket p)
|
||||
{
|
||||
char *buffer;
|
||||
|
||||
buffer = malloc(PREZZY_PACKET_MAX * sizeof(char));
|
||||
|
||||
if (p.type == PLT_STRING) {
|
||||
snprintf(buffer, PREZZY_PACKET_MAX, "%c%s\n",
|
||||
p.property, p.pString);
|
||||
} else {
|
||||
snprintf(buffer, PREZZY_PACKET_MAX, "%c%ld\n",
|
||||
p.property, p.pInteger);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
PrezzyIpcPacket *
|
||||
makeIpcPacket(const char *buffer)
|
||||
{
|
||||
PrezzyIpcPacket *m;
|
||||
int i;
|
||||
|
||||
m = malloc(sizeof(PrezzyIpcPacket));
|
||||
|
||||
/* extract property */
|
||||
m->property = buffer[0];
|
||||
if (m->property < 0 || m->property >= PREZZY_PROPERTY_MAX)
|
||||
return NULL;
|
||||
|
||||
/* determine payload type */
|
||||
m->type = payloadTypeMapping[m->property];
|
||||
|
||||
switch (m->type) {
|
||||
case PLT_STRING:
|
||||
m->pString = NULL;
|
||||
for (i = 1; buffer[i] != '\n' && buffer[i] != '\0'
|
||||
&& i < PREZZY_PACKET_MAX; i++) {
|
||||
m->pString = realloc(m->pString, (i + 1) * sizeof(char));
|
||||
m->pString[i - 1] = buffer[i];
|
||||
m->pString[i] = '\0';
|
||||
}
|
||||
break;
|
||||
case PLT_INT64:
|
||||
m->pInteger = strtol(buffer + 1, NULL, 10);
|
||||
break;
|
||||
case PLT_INT:
|
||||
m->pInteger = squashLong(strtol(buffer + 1, NULL, 10));
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
int
|
||||
squashLong(long l)
|
||||
{
|
||||
return (l >= INT_MIN && l <= INT_MAX) ? l : INT_MAX ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy string src to buffer dst of size dsize. At most dsize-1
|
||||
* chars will be copied. Always NUL terminates (unless dsize == 0).
|
||||
* Returns strlen(src); if retval >= dsize, truncation occurred.
|
||||
*/
|
||||
size_t
|
||||
strbcpy(char *dst, const char *src, size_t dsize)
|
||||
{
|
||||
const char *osrc = src;
|
||||
size_t nleft = dsize;
|
||||
|
||||
/* Copy as many bytes as will fit. */
|
||||
if (nleft != 0) {
|
||||
while (--nleft != 0) {
|
||||
if ((*dst++ = *src++) == '\0')
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Not enough room in dst, add NUL and traverse rest of src. */
|
||||
if (nleft == 0) {
|
||||
if (dsize != 0)
|
||||
*dst = '\0'; /* NUL-terminate dst */
|
||||
while (*src++)
|
||||
;
|
||||
}
|
||||
|
||||
return (src - osrc - 1); /* count does not include NUL */
|
||||
}
|
||||
|
||||
char *
|
||||
stringFrom(const char *reference)
|
||||
{
|
||||
char *buffer;
|
||||
size_t len;
|
||||
|
||||
len = strlen(reference) + 1;
|
||||
buffer = malloc(len * sizeof(char));
|
||||
strbcpy(buffer, reference, len);
|
||||
|
||||
return buffer;
|
||||
}
|
73
prezzyipc.h
Normal file
73
prezzyipc.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* prezzyipc.h
|
||||
* Copyright (c) 2024 Jeremy Baxter.
|
||||
*/
|
||||
|
||||
#ifndef _PREZZYIPC_H_
|
||||
#define _PREZZYIPC_H_
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define PREZZY_PACKET_MAX 1024
|
||||
#define PREZZY_SOCK "/tmp/prezzyd.sock"
|
||||
|
||||
typedef char byte;
|
||||
|
||||
typedef enum {
|
||||
PREZZY_STATE = 1,
|
||||
PREZZY_DETAILS = 2,
|
||||
PREZZY_LARGE_IMAGE = 3,
|
||||
PREZZY_LARGE_TOOLTIP = 4,
|
||||
PREZZY_ICON = 5,
|
||||
PREZZY_ICON_TOOLTIP = 6,
|
||||
PREZZY_PARTY_SIZE = 7,
|
||||
PREZZY_PARTY_LIMIT = 8,
|
||||
PREZZY_TIMESTAMP_START = 9,
|
||||
PREZZY_TIMESTAMP_END = 10,
|
||||
PREZZY_PROPERTY_MAX = 11
|
||||
} PrezzyProperty;
|
||||
|
||||
typedef enum {
|
||||
PLT_STRING = 1,
|
||||
PLT_INT64 = 2,
|
||||
PLT_INT = 3,
|
||||
PLT_MAX = 4
|
||||
} PrezzyPayloadType;
|
||||
|
||||
#ifdef _PREZZYIPC_C_
|
||||
PrezzyPayloadType payloadTypeMapping[PREZZY_PROPERTY_MAX] = {
|
||||
[PREZZY_STATE] = PLT_STRING,
|
||||
[PREZZY_DETAILS] = PLT_STRING,
|
||||
[PREZZY_LARGE_IMAGE] = PLT_STRING,
|
||||
[PREZZY_LARGE_TOOLTIP] = PLT_STRING,
|
||||
[PREZZY_ICON] = PLT_STRING,
|
||||
[PREZZY_ICON_TOOLTIP] = PLT_STRING,
|
||||
[PREZZY_PARTY_SIZE] = PLT_INT,
|
||||
[PREZZY_PARTY_LIMIT] = PLT_INT,
|
||||
[PREZZY_TIMESTAMP_START] = PLT_INT64,
|
||||
[PREZZY_TIMESTAMP_END] = PLT_INT64
|
||||
};
|
||||
#else
|
||||
extern PrezzyPayloadType payloadTypeMapping[PREZZY_PROPERTY_MAX];
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
PrezzyProperty property;
|
||||
PrezzyPayloadType type;
|
||||
char *pString;
|
||||
int64_t pInteger;
|
||||
} PrezzyIpcPacket;
|
||||
|
||||
void dumpPacket(PrezzyIpcPacket);
|
||||
char *fromIpcPacket(PrezzyIpcPacket);
|
||||
PrezzyIpcPacket *makeIpcPacket(const char *);
|
||||
int squashLong(long);
|
||||
size_t strbcpy(char *, const char *, size_t);
|
||||
char *stringFrom(const char *);
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue