116 lines
3.8 KiB
C
116 lines
3.8 KiB
C
#include "replaymod.h"
|
|
#include "proxy.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <memory.h>
|
|
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/uio.h>
|
|
|
|
#include <endian.h>
|
|
|
|
static const char json_format[]="{\"singleplayer\":false,\"fileFormat\":\"MCPR\",\"fileFormatVersion\":9,\"generator\":\"ACTools proxy\",\"selfId\":-1,"
|
|
"\"serverName\":\"%s\","
|
|
"\"date\":%lu,"
|
|
"\"duration\":%u,"
|
|
"\"mcversion\":\"%s\",\"players\":[",
|
|
json_format_end[]="]}\n";
|
|
|
|
void replay_init_context(struct context *ctx, const char *restrict version/*, const uint8_t *restrict buffer, uint32_t len*/) {
|
|
replay_free_context(ctx);
|
|
|
|
char buf[32];
|
|
time_t t = time(NULL);
|
|
struct tm *tm = localtime(&t);
|
|
sprintf(buf, "%d_%02d_%02d_%02d_%02d_%02d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
|
|
mkdir(buf, S_IRWXU);
|
|
|
|
int dirfd=open(buf, O_DIRECTORY);
|
|
|
|
ctx->replay.replayfileFD=openat(dirfd, "recording.tmcpr", O_CREAT|O_CLOEXEC|O_WRONLY|O_NONBLOCK, S_IREAD|S_IWRITE);
|
|
ctx->replay.replayinfoFD=openat(dirfd, "metaData.json", O_CREAT|O_CLOEXEC|O_WRONLY, S_IREAD|S_IWRITE);
|
|
|
|
if(ctx->replay.replayfileFD == -1 || ctx->replay.replayinfoFD == -1) {
|
|
perror("openat() failed: ");
|
|
if(ctx->replay.replayfileFD != -1)
|
|
close(ctx->replay.replayfileFD);
|
|
else if (ctx->replay.replayinfoFD != -1)
|
|
close(ctx->replay.replayinfoFD);
|
|
ctx->replay.replayfileFD = -1;
|
|
return;
|
|
}
|
|
|
|
// fcntl(ctx->replay.replayfileFD, F_SETFL, fcntl(ctx->replay.replayfileFD, F_GETFL) | O_NONBLOCK);
|
|
|
|
gettimeofday(&ctx->replay.startTime, NULL);//Can fail on linux with EFAULT
|
|
ctx->replay.startTime.tv_usec/=1000;
|
|
ctx->replay.startTime.tv_usec+=ctx->replay.startTime.tv_sec*1000;
|
|
|
|
ctx->replay.versionName = version;
|
|
ctx->replay.UUIDs = malloc(4*sizeof(uint8_t*));
|
|
void *ptr = malloc(4*37);
|
|
ctx->replay.UUIDs[0] = ptr;
|
|
ctx->replay.UUIDs[1] = ptr+37;
|
|
ctx->replay.UUIDs[2] = ptr+(2*37);
|
|
ctx->replay.UUIDs[3] = ptr+(3*37);
|
|
ctx->replay.uuidcount = 4;
|
|
ctx->replay.uuidused = 0;
|
|
}
|
|
void replay_free_context(struct context *ctx) {
|
|
if(ctx->replay.replayfileFD == -1)
|
|
return;
|
|
close(ctx->replay.replayfileFD);
|
|
ctx->replay.replayfileFD = -1;
|
|
if(ctx->replay.replayinfoFD != -1) {
|
|
struct timeval now;
|
|
gettimeofday(&now, NULL);
|
|
uint32_t diff = (uint32_t)(now.tv_usec/1000 + now.tv_sec*1000 - ctx->replay.startTime.tv_usec);//msecs in tv_usec
|
|
|
|
dprintf(ctx->replay.replayinfoFD, json_format, "127.0.0.1", ctx->replay.startTime.tv_usec, diff, ctx->replay.versionName);
|
|
for(uint8_t i = 0; i < ctx->replay.uuidcount; i++) {
|
|
if(i)
|
|
dprintf(ctx->replay.replayinfoFD, ",");
|
|
dprintf(ctx->replay.replayinfoFD, "\"%s\"", ctx->replay.UUIDs[i]);
|
|
}
|
|
dprintf(ctx->replay.replayinfoFD, json_format_end);
|
|
close(ctx->replay.replayinfoFD);
|
|
ctx->replay.replayinfoFD = -1;
|
|
}
|
|
}
|
|
|
|
void replay_write_packet(struct context *ctx, const uint8_t *restrict buffer, uint32_t len) {
|
|
if(ctx->replay.replayfileFD == -1)
|
|
return;
|
|
|
|
struct timeval now;
|
|
gettimeofday(&now, NULL);
|
|
|
|
uint32_t diff = (uint32_t)(now.tv_usec/1000 + now.tv_sec*1000 - ctx->replay.startTime.tv_usec);//msecs in tv_usec
|
|
|
|
uint32_t buf[2] = {htobe32(diff), htobe32(len)};
|
|
|
|
struct iovec iv[2]={{buf, 2*4}, {(void*)buffer, len}};
|
|
if(writev(ctx->replay.replayfileFD, iv, 2) == -1)
|
|
perror("writev() failed");
|
|
}
|
|
|
|
void replay_add_uuid(struct context *ctx, const uint8_t *restrict buffer) {
|
|
for(uint32_t i=0; i<ctx->replay.uuidused; i++) {
|
|
if(memcmp(buffer, ctx->replay.UUIDs[i], 36) == 0)
|
|
return;//Already added
|
|
}
|
|
|
|
if(ctx->replay.uuidused == ctx->replay.uuidcount) {
|
|
ctx->replay.UUIDs=realloc(ctx->replay.UUIDs, (++ctx->replay.uuidcount)*sizeof(uint8_t*));
|
|
ctx->replay.UUIDs[ctx->replay.uuidused] = malloc(37);
|
|
}
|
|
|
|
memcpy(ctx->replay.UUIDs[ctx->replay.uuidused], buffer, 36);
|
|
(ctx->replay.UUIDs[ctx->replay.uuidused])[36]=0;
|
|
ctx->replay.uuidused++;
|
|
}
|