Files
openairinterface5g/common/utils/T/tracer/replay.c
T
Cedric Roux 2fa337d853 T bugfix: include size of 'length' to allocated memory
The way allocation is done (granularity of 64KiB) makes a crash more
difficult to achieve, but if a trace is exactly 64KiB, we miss 4 bytes
in the realloc and then anything may happen.
2025-06-02 11:19:23 +02:00

192 lines
4.6 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include "utils.h"
#include "../T_defs.h"
#define DEFAULT_REMOTE_PORT 2021
/* replay.c does not know anything about events - it just has the array
* is_on that grows each time replay.c sees a type that does not fit in
* there (the idea is to isolate replay.c as maximum by not using unneeded
* information)
*/
int *is_on;
int is_on_size;
/* this lock is used to protect access to is_on/is_on_size */
pthread_mutex_t biglock = PTHREAD_MUTEX_INITIALIZER;
void set_is_on_size(int size)
{
is_on = realloc(is_on, size * sizeof(int)); if (is_on == NULL) abort();
memset(is_on + is_on_size, 0, (size - is_on_size) * sizeof(int));
is_on_size = size;
}
void lock(void)
{
if (pthread_mutex_lock(&biglock)) abort();
}
void unlock(void)
{
if (pthread_mutex_unlock(&biglock)) abort();
}
#define QUIT(x) do { printf("%s\n", x); exit(1); } while(0)
void get_message(int s)
{
char t;
int l;
int id;
int on;
if (read(s, &t, 1) != 1) QUIT("get_message fails");
lock();
switch (t) {
case 0:
/* toggle all those IDs */
if (read(s, &l, sizeof(int)) != sizeof(int)) QUIT("get_message fails");
while (l) {
if (read(s, &id, sizeof(int)) != sizeof(int)) QUIT("get_message fails");
if (id > is_on_size - 1) set_is_on_size(id + 1);
is_on[id] = 1 - is_on[id];
l--;
}
break;
case 1:
/* set IDs as given */
/* optimize? */
if (read(s, &l, sizeof(int)) != sizeof(int)) QUIT("get_message fails");
if (l > is_on_size) set_is_on_size(l);
id = 0;
while (l) {
if (read(s, &on, sizeof(int)) != sizeof(int))
QUIT("get_message fails");
is_on[id] = on;
id++;
l--;
}
break;
case 2: break; /* do nothing, this message is to wait for local tracer */
default: abort();
}
unlock();
}
void *get_message_thread(void *_socket)
{
int socket = *(int *)_socket;
while (1) get_message(socket);
return NULL;
}
void usage(void)
{
printf(
"options:\n"
" -i <input file> this option is mandatory\n"
" -p <port> wait connection on given port (default %d)\n"
" -w user must press a key after each sent event\n",
DEFAULT_REMOTE_PORT
);
exit(1);
}
#define ERR printf("ERROR: read file %s failed\n", input_filename)
int main(int n, char **v)
{
int port = DEFAULT_REMOTE_PORT;
char *input_filename = NULL;
int i;
int socket;
FILE *in;
int do_send;
int do_wait = 0;
for (i = 1; i < n; i++) {
if (!strcmp(v[i], "-h") || !strcmp(v[i], "--help")) usage();
if (!strcmp(v[i], "-i"))
{ if (i > n-2) usage(); input_filename = v[++i]; continue; }
if (!strcmp(v[i], "-p"))
{ if (i > n-2) usage(); port = atoi(v[++i]); continue; }
if (!strcmp(v[i], "-w")) { do_wait = 1; continue; }
usage();
}
if (input_filename == NULL) {
printf("ERROR: provide an input file (-i)\n");
exit(1);
}
in = fopen(input_filename, "r");
if (in == NULL) { perror(input_filename); abort(); }
socket = get_connection("0.0.0.0", port);
/* get first message to activate selected traces */
get_message(socket);
new_thread(get_message_thread, &socket);
OBUF ebuf = {.osize = 0, .omaxsize = 0, .obuf = NULL};
while (1) {
int type;
int32_t length;
char *v;
int vpos = 0;
/* read event from file */
if (fread(&length, 4, 1, in) != 1) break;
if (ebuf.omaxsize < length + 4) {
ebuf.omaxsize = (length + 4 + 65535) & ~65535;
ebuf.obuf = realloc(ebuf.obuf, ebuf.omaxsize);
if (ebuf.obuf == NULL) { printf("out of memory\n"); exit(1); }
}
v = ebuf.obuf;
memcpy(v+vpos, &length, 4);
vpos += 4;
#ifdef T_SEND_TIME
if (length < sizeof(struct timespec)) { ERR; break; }
if (fread(v+vpos, sizeof(struct timespec), 1, in) != 1) { ERR; break; }
vpos += sizeof(struct timespec);
length -= sizeof(struct timespec);
#endif
if (length < sizeof(int)) { ERR; break; }
if (fread(&type, sizeof(int), 1, in) != 1) { ERR; break; }
memcpy(v+vpos, &type, sizeof(int));
vpos += sizeof(int);
length -= sizeof(int);
if (length) if (fread(v+vpos, length, 1, in) != 1) { ERR; break; }
vpos += length;
/* only send if configured to do so */
lock();
if (type < 0) do_send = 1;
else {
if (type > is_on_size - 1) set_is_on_size(type+1);
do_send = is_on[type];
}
unlock();
if (do_send)
if (socket_send(socket, v, vpos) != 0)
{ printf("ERROR: socket writing failed\n"); abort(); }
if (do_send && do_wait) getchar();
}
fclose(in);
close(socket);
return 0;
}