summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2023-12-31 17:29:19 -0500
committerAndrew Opalach <andrew@akon.city> 2023-12-31 17:29:19 -0500
commit842fed76fdb6762e10d1571255229a80c8505b04 (patch)
treea2d46bc3ba63a91cf6ca00d285716a084cd4da8b /src
parentb0f53d634813af0a038d4faf6fa71d90d9aa0845 (diff)
downloadlibnaunet-842fed76fdb6762e10d1571255229a80c8505b04.tar.gz
libnaunet-842fed76fdb6762e10d1571255229a80c8505b04.tar.bz2
libnaunet-842fed76fdb6762e10d1571255229a80c8505b04.zip
Update
- Add aki_poll and aki_fs_event - Various aki_file improvments - Add grow mode to aki_packet_pool - aki_packet_stream_pause/resume -> cork - Misc fixes and improvments Signed-off-by: Andrew Opalach <andrew@akon.city>
Diffstat (limited to 'src')
-rw-r--r--src/common.c7
-rw-r--r--src/common.h4
-rw-r--r--src/fs_event.c56
-rw-r--r--src/fs_event.h25
-rw-r--r--src/line_processor.c1
-rw-r--r--src/packet_pool.c8
-rw-r--r--src/packet_stream.c14
-rw-r--r--src/packet_stream.h3
-rw-r--r--src/poll.c32
-rw-r--r--src/poll.h18
-rw-r--r--src/socket/socket.h20
-rw-r--r--src/socket/socket_linux.c28
-rw-r--r--src/util/error.c6
-rw-r--r--src/util/error.h12
-rw-r--r--src/util/file/file.h11
-rw-r--r--src/util/file/file_linux.c43
-rw-r--r--src/util/file/file_stdio.c4
-rw-r--r--src/util/file/util.c10
-rw-r--r--src/util/packet.c17
-rw-r--r--src/util/packet.h7
20 files changed, 271 insertions, 55 deletions
diff --git a/src/common.c b/src/common.c
index b9ee5c2..3c76cbd 100644
--- a/src/common.c
+++ b/src/common.c
@@ -1,5 +1,6 @@
#include <al/lib.h>
#include <al/random.h>
+#include <locale.h>
#ifndef _WIN32
#include <unistd.h>
@@ -10,8 +11,10 @@
#include "common.h"
#include "winwrap.h"
-void aki_common_init(void)
+bool aki_common_init(void)
{
+ if (!setlocale(LC_ALL, "")) return false;
+
al_malloc_init();
al_rand_init();
@@ -24,6 +27,8 @@ void aki_common_init(void)
GetSystemInfo(&info);
al_set_page_size(info.dwPageSize);
#endif
+
+ return true;
}
void aki_common_close(void)
diff --git a/src/common.h b/src/common.h
index da4b3e3..c70cc24 100644
--- a/src/common.h
+++ b/src/common.h
@@ -1,4 +1,6 @@
#pragma once
-void aki_common_init(void);
+#include <al/types.h>
+
+bool aki_common_init(void);
void aki_common_close(void);
diff --git a/src/fs_event.c b/src/fs_event.c
new file mode 100644
index 0000000..8edce13
--- /dev/null
+++ b/src/fs_event.c
@@ -0,0 +1,56 @@
+#include <al/log.h>
+
+#include "util/error.h"
+
+#include "fs_event.h"
+
+static void event_callback(struct ev_loop *loop, ev_io *w, s32 revents)
+{
+ (void)loop;
+ struct aki_fs_event *fs = (struct aki_fs_event *)w->data;
+ (void)revents;
+ struct inotify_event event = { 0 };
+ ssize_t ret = aki_read(fs->fd, &event, sizeof(struct inotify_event));
+ if (ret == sizeof(struct inotify_event)) {
+ al_assert(event.wd == fs->wd);
+ al_assert(event.len == 0);
+ fs->callback(fs->userdata, &event);
+ }
+}
+
+void aki_fs_event_init(struct aki_fs_event *fs, str *path, u32 mask,
+ void (*callback)(void *, struct inotify_event *), void *userdata)
+{
+ fs->fd = inotify_init();
+ aki_fd_set_blocking(fs->fd, true);
+ fs->mask = mask;
+ fs->callback = callback;
+ fs->userdata = userdata;
+ fs->path = al_str_to_c_str(path);
+ fs->event.data = fs;
+ ev_io_init(&fs->event, event_callback, fs->fd, EV_READ);
+}
+
+bool aki_fs_event_start(struct aki_fs_event *fs, struct aki_event_loop *loop)
+{
+ fs->loop = loop;
+ fs->wd = inotify_add_watch(fs->fd, fs->path, fs->mask);
+ if (fs->wd == -1) {
+ al_log_error("fs_event", "inotify_add_watch(%s) failed (%s)", fs->path, aki_strerror(errno));
+ return false;
+ }
+ ev_io_start(fs->loop->ev, &fs->event);
+ return true;
+}
+
+void aki_fs_event_stop(struct aki_fs_event *fs)
+{
+ inotify_rm_watch(fs->fd, fs->wd);
+ ev_io_stop(fs->loop->ev, &fs->event);
+}
+
+void aki_fs_event_free(struct aki_fs_event *fs)
+{
+ close(fs->fd);
+ al_free(fs->path);
+}
diff --git a/src/fs_event.h b/src/fs_event.h
new file mode 100644
index 0000000..d45d7af
--- /dev/null
+++ b/src/fs_event.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include <al/str.h>
+#include <sys/inotify.h>
+
+#include "socket/socket.h"
+
+#include "loop.h"
+
+struct aki_fs_event {
+ s32 fd;
+ u32 mask;
+ char *path;
+ s32 wd;
+ ev_io event;
+ struct aki_event_loop *loop;
+ void (*callback)(void *, struct inotify_event *);
+ void *userdata;
+};
+
+void aki_fs_event_init(struct aki_fs_event *fs, str *path, u32 mask,
+ void (*callback)(void *, struct inotify_event *), void *userdata);
+bool aki_fs_event_start(struct aki_fs_event *fs, struct aki_event_loop *loop);
+void aki_fs_event_stop(struct aki_fs_event *fs);
+void aki_fs_event_free(struct aki_fs_event *fs);
diff --git a/src/line_processor.c b/src/line_processor.c
index de86dab..158c5cb 100644
--- a/src/line_processor.c
+++ b/src/line_processor.c
@@ -150,4 +150,5 @@ void aki_line_processor_stop(struct aki_line_processor *pro)
}
}
al_array_free(pro->clients);
+ al_str_free(&pro->delim);
}
diff --git a/src/packet_pool.c b/src/packet_pool.c
index 4c942b1..683efcb 100644
--- a/src/packet_pool.c
+++ b/src/packet_pool.c
@@ -79,12 +79,18 @@ void aki_packet_pool_init_ex(struct aki_packet_pool *pool, u32 size, struct aki_
init_internal(pool, size, loop, mode, callback, userdata);
}
+static const bool grow = false;
+
struct aki_packet *aki_packet_pool_get(struct aki_packet_pool *pool)
{
al_assert(pool->mode == AKI_PACKET_POOL_MODE_POOL);
aki_mutex_lock(&pool->mutex);
if (!pool->disabled && !pool->empty.size) {
- aki_cond_wait(&pool->cond, &pool->mutex);
+ if (grow) {
+ al_array_push(pool->empty, aki_packet_create());
+ } else {
+ aki_cond_wait(&pool->cond, &pool->mutex);
+ }
}
if (pool->disabled) {
aki_mutex_unlock(&pool->mutex);
diff --git a/src/packet_stream.c b/src/packet_stream.c
index 5c415aa..0096f7c 100644
--- a/src/packet_stream.c
+++ b/src/packet_stream.c
@@ -202,16 +202,12 @@ void aki_packet_stream_connect(struct aki_packet_stream *stream,
ev_timer_start(loop->ev, &stream->timer);
}
-void aki_packet_stream_pause(struct aki_packet_stream *stream)
+void aki_packet_stream_cork(struct aki_packet_stream *stream, bool cork)
{
- if (stream->connected && stream->revent.active) {
+ if (!stream->connected) return;
+ if (cork && stream->revent.active) {
ev_io_stop(stream->loop->ev, &stream->revent);
- }
-}
-
-void aki_packet_stream_resume(struct aki_packet_stream *stream)
-{
- if (stream->connected && !stream->revent.active) {
+ } else if (!cork && !stream->revent.active) {
ev_io_start(stream->loop->ev, &stream->revent);
}
}
@@ -238,7 +234,7 @@ void aki_packet_stream_disconnect(struct aki_packet_stream *stream)
{
if (stream->connected) {
aki_socket_shutdown(&stream->s);
- aki_packet_stream_resume(stream);
+ aki_packet_stream_cork(stream, false);
}
}
diff --git a/src/packet_stream.h b/src/packet_stream.h
index 4e83639..964bb9b 100644
--- a/src/packet_stream.h
+++ b/src/packet_stream.h
@@ -44,8 +44,7 @@ void aki_packet_stream_listen(struct aki_packet_stream *stream,
struct aki_event_loop *loop, str *addr, s32 port);
void aki_packet_stream_connect(struct aki_packet_stream *stream,
struct aki_event_loop *loop, str *addr, s32 port);
-void aki_packet_stream_pause(struct aki_packet_stream *stream);
-void aki_packet_stream_resume(struct aki_packet_stream *stream);
+void aki_packet_stream_cork(struct aki_packet_stream *stream, bool cork);
void aki_packet_stream_send_packet(struct aki_packet_stream *stream, struct aki_packet *packet);
void aki_packet_stream_flush(struct aki_packet_stream *stream, void (*flushed_callback)(void *));
void aki_packet_stream_disconnect(struct aki_packet_stream *stream);
diff --git a/src/poll.c b/src/poll.c
new file mode 100644
index 0000000..ff04a63
--- /dev/null
+++ b/src/poll.c
@@ -0,0 +1,32 @@
+#include "poll.h"
+
+static void event_callback(struct ev_loop *loop, ev_io *w, s32 revents)
+{
+ (void)loop;
+ struct aki_poll *poll = (struct aki_poll *)w->data;
+ poll->callback(poll->userdata, revents);
+}
+
+void aki_poll_init(struct aki_poll *poll, void (*callback)(void *, s32 revents), void *userdata)
+{
+ poll->callback = callback;
+ poll->userdata = userdata;
+ poll->event.data = poll;
+ ev_init(&poll->event, event_callback);
+}
+
+void aki_poll_set(struct aki_poll *poll, s32 fd, s32 events)
+{
+ ev_io_set(&poll->event, fd, events);
+}
+
+void aki_poll_start(struct aki_poll *poll, struct aki_event_loop *loop)
+{
+ poll->loop = loop;
+ ev_io_start(poll->loop->ev, &poll->event);
+}
+
+void aki_poll_stop(struct aki_poll *poll)
+{
+ ev_io_stop(poll->loop->ev, &poll->event);
+}
diff --git a/src/poll.h b/src/poll.h
new file mode 100644
index 0000000..6a0e826
--- /dev/null
+++ b/src/poll.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "loop.h"
+
+#define AKI_POLL_READ EV_READ
+#define AKI_POLL_WRITE EV_WRITE
+
+struct aki_poll {
+ ev_io event;
+ struct aki_event_loop *loop;
+ void (*callback)(void *, s32 revents);
+ void *userdata;
+};
+
+void aki_poll_init(struct aki_poll *poll, void (*callback)(void *, s32 revents), void *userdata);
+void aki_poll_start(struct aki_poll *poll, struct aki_event_loop *loop);
+void aki_poll_set(struct aki_poll *poll, s32 fd, s32 events);
+void aki_poll_stop(struct aki_poll *poll);
diff --git a/src/socket/socket.h b/src/socket/socket.h
index 4971c1c..c0cf796 100644
--- a/src/socket/socket.h
+++ b/src/socket/socket.h
@@ -1,11 +1,14 @@
#pragma once
#ifndef _WIN32
+#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/in.h>
+#include <poll.h>
#include <sys/un.h>
+#include <sys/eventfd.h>
#else
#include "../winwrap.h"
#endif
@@ -34,15 +37,20 @@ struct aki_socket {
#ifndef _WIN32
#define aki_read read
#define aki_write write
-#define aki_htons htons
-#define aki_htonl htonl
-#define aki_ntohs ntohs
#else
#define aki_read _read
#define aki_write _write
-#define aki_htons(...) 0
-#define aki_htonl(...) 0
-#define aki_ntohs(...) 0
+#endif
+
+#define aki_htons htons
+#define aki_htonl htonl
+#define aki_ntohs ntohs
+
+#ifndef _WIN32 // Posix-only helpers.
+#define aki_pollfd pollfd
+#define aki_nfds nfds_t
+void aki_fd_set_blocking(s32 fd, bool blocking);
+s32 aki_poll_fds(struct aki_pollfd *fds, aki_nfds nfds, s64 timeout_ns);
#endif
bool aki_socket_init(struct aki_socket *s);
diff --git a/src/socket/socket_linux.c b/src/socket/socket_linux.c
index 7bc9ea9..3d141b7 100644
--- a/src/socket/socket_linux.c
+++ b/src/socket/socket_linux.c
@@ -9,6 +9,27 @@
#include "socket.h"
+void aki_fd_set_blocking(s32 fd, bool blocking)
+{
+ s32 flags = fcntl(fd, F_GETFL, 0);
+ al_assert(flags != -1);
+ flags = blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);
+ s32 ret = fcntl(fd, F_SETFL, flags);
+ al_assert(ret == 0);
+}
+
+#define AKI_TIME_S_TO_NS(s) ((s) * INT64_C(1000000000))
+
+// https://github.com/mpv-player/mpv/blob/e575ec4fc3654387c7358bd3640877ef32628d2c/osdep/poll_wrapper.c#L29
+s32 aki_poll_fds(struct aki_pollfd *fds, aki_nfds nfds, s64 timeout_ns)
+{
+ struct timespec ts;
+ ts.tv_sec = timeout_ns / AKI_TIME_S_TO_NS(1);
+ ts.tv_nsec = timeout_ns % AKI_TIME_S_TO_NS(1);
+ struct timespec *tsp = timeout_ns >= 0 ? &ts : NULL;
+ return ppoll(fds, nfds, tsp, NULL);
+}
+
bool aki_socket_init(struct aki_socket *s)
{
switch (s->type) {
@@ -33,11 +54,7 @@ bool aki_socket_init(struct aki_socket *s)
void aki_socket_set_blocking(struct aki_socket *s, bool blocking)
{
- s32 flags = fcntl(s->sock, F_GETFL, 0);
- al_assert(flags != -1);
- flags = blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);
- s32 ret = fcntl(s->sock, F_SETFL, flags);
- al_assert(ret == 0);
+ aki_fd_set_blocking(s->sock, blocking);
}
void aki_socket_set_no_delay(struct aki_socket *s, s32 no_delay)
@@ -251,4 +268,3 @@ void aki_socket_close(struct aki_socket *s)
{
close(s->sock);
}
-
diff --git a/src/util/error.c b/src/util/error.c
index f055416..7e09d20 100644
--- a/src/util/error.c
+++ b/src/util/error.c
@@ -1,7 +1,3 @@
#include "error.h"
-#ifndef _WIN32
-__thread char errorbuf[ERROR_STR_MAXLEN];
-#else
-__declspec(thread) char errorbuf[ERROR_STR_MAXLEN];
-#endif
+__al_thread char errorbuf[AKI_ERROR_STR_MAXLEN];
diff --git a/src/util/error.h b/src/util/error.h
index c7edd82..0849ddb 100644
--- a/src/util/error.h
+++ b/src/util/error.h
@@ -2,20 +2,16 @@
#include <errno.h>
-#define ERROR_STR_MAXLEN 94
+#define AKI_ERROR_STR_MAXLEN 94
-#ifndef _WIN32
-extern __thread char errorbuf[ERROR_STR_MAXLEN];
-#else
-extern __declspec(thread) char errorbuf[ERROR_STR_MAXLEN];
-#endif
+extern __al_thread char errorbuf[AKI_ERROR_STR_MAXLEN];
static inline char *aki_strerror(s32 errnum)
{
#ifndef _WIN32
- (void)!strerror_r(errnum, errorbuf, ERROR_STR_MAXLEN);
+ (void)!strerror_r(errnum, errorbuf, AKI_ERROR_STR_MAXLEN);
#else
- strerror_s(errorbuf, ERROR_STR_MAXLEN, errnum);
+ strerror_s(errorbuf, AKI_ERROR_STR_MAXLEN, errnum);
#endif
return errorbuf;
}
diff --git a/src/util/file/file.h b/src/util/file/file.h
index 465d76a..a6611bd 100644
--- a/src/util/file/file.h
+++ b/src/util/file/file.h
@@ -14,6 +14,13 @@
#endif
#include <al/str.h>
+#include <al/lib.h>
+
+enum {
+ AKI_FILE_READONLY = 1,
+ AKI_FILE_CREATE = 1 << 1,
+ AKI_FILE_LOCK = 1 << 2
+};
enum {
AKI_ENTRY_FILE = 0,
@@ -60,8 +67,9 @@ struct aki_dir_entry {
str path;
};
-bool aki_file_open(struct aki_file *file, str *path, bool create);
+bool aki_file_open(struct aki_file *file, str *path, s32 flags);
bool aki_file_exists(str *path);
+bool aki_file_create(str *path);
bool aki_file_truncate(struct aki_file *file, off_t size);
off_t aki_file_seek(struct aki_file *file, off_t offset, s32 whence);
size_t aki_file_get_filesize(struct aki_file *file);
@@ -69,6 +77,7 @@ bool aki_file_write(struct aki_file *file, void *buf, size_t size);
bool aki_file_read(struct aki_file *file, void *buf, size_t size);
s32 aki_file_read_as_str(struct aki_file *file, str *out);
s32 aki_file_read_as_c_str(struct aki_file *file, char **out);
+s32 aki_file_replace(struct aki_file *file, str *buf);
void *aki_file_mmap(struct aki_file *file);
void *aki_file_mremap(struct aki_file *file, size_t size, void *old_map);
void aki_file_munmap(struct aki_file *file, void *map);
diff --git a/src/util/file/file_linux.c b/src/util/file/file_linux.c
index 708bd2d..f916e0b 100644
--- a/src/util/file/file_linux.c
+++ b/src/util/file/file_linux.c
@@ -1,16 +1,33 @@
-#include <sys/mman.h>
#include <al/log.h>
+#include <sys/mman.h>
#include "../error.h"
#include "file.h"
-bool aki_file_open(struct aki_file *file, str *path, bool create)
+static bool lock_file_internal(s32 fd)
+{
+ struct flock l = {
+ .l_type = F_WRLCK,
+ .l_whence = SEEK_SET,
+ .l_start = 0,
+ .l_len = 0
+ };
+ if (fcntl(fd, F_SETLKW, &l) == -1) {
+ al_log_error("file", "fcntl(F_SETLKW) failed (%s).", aki_strerror(errno));
+ close(fd);
+ return false;
+ }
+ return true;
+}
+
+bool aki_file_open(struct aki_file *file, str *path, s32 flags)
{
+ al_assert(!((flags & AKI_FILE_READONLY) && (flags & AKI_FILE_LOCK)));
char *c_str = al_str_to_c_str(path);
- s32 flags = O_RDWR;
- if (create) flags |= O_CREAT;
- file->fd = open(c_str, flags, 0666);
+ s32 oflags = (flags & AKI_FILE_READONLY) ? O_RDONLY : O_RDWR;
+ if (flags & AKI_FILE_CREATE) oflags |= O_CREAT;
+ file->fd = open(c_str, oflags, 0666);
al_free(c_str);
if (file->fd == -1) {
al_log_error("file", "open(%.*s) failed (%s).", AL_STR_PRINTF(path), aki_strerror(errno));
@@ -24,6 +41,7 @@ bool aki_file_open(struct aki_file *file, str *path, bool create)
return false;
}
file->filesize = sb.st_size;
+ if (flags & AKI_FILE_LOCK) lock_file_internal(file->fd);
return true;
}
@@ -32,12 +50,19 @@ bool aki_file_exists(str *path)
char *c_str = al_str_to_c_str(path);
s32 ret = access(c_str, F_OK);
al_free(c_str);
- if (ret != 0) {
- al_log_error("file", "access(%.*s, F_OK) failed (%s).", AL_STR_PRINTF(path), aki_strerror(errno));
- }
return ret == 0;
}
+bool aki_file_create(str *path)
+{
+ struct aki_file file;
+ if (aki_file_open(&file, path, AKI_FILE_CREATE)) {
+ aki_file_close(&file);
+ return true;
+ }
+ return false;
+}
+
off_t aki_file_seek(struct aki_file *file, off_t offset, s32 whence)
{
off_t res = lseek(file->fd, offset, whence);
@@ -98,7 +123,6 @@ void *aki_file_mmap(struct aki_file *file)
void *aki_file_mremap(struct aki_file *file, size_t size, void *old_map)
{
- printf("old_size: %zu, new_size: %zu\n", file->filesize, size);
void *map = mremap(old_map, file->filesize, size, MREMAP_MAYMOVE);
if (map == MAP_FAILED) {
al_log_error("file", "mremap(%p, %zu, %zu) failed (%s).", old_map,
@@ -152,6 +176,7 @@ bool aki_dir_exists(str *path)
}
return false;
}
+ closedir(dir.dir);
return true;
}
diff --git a/src/util/file/file_stdio.c b/src/util/file/file_stdio.c
index 52d8761..fa1e4ff 100644
--- a/src/util/file/file_stdio.c
+++ b/src/util/file/file_stdio.c
@@ -4,10 +4,10 @@
#include "file.h"
-bool aki_file_open(struct aki_file *file, str *path, bool create)
+bool aki_file_open(struct aki_file *file, str *path, s32 flags)
{
char *c_str = al_str_to_c_str(path);
- const char *mode = create ? "wb+" : "rb+";
+ const char *mode = (flags & AKI_FILE_CREATE) ? "wb+" : "rb+";
#ifndef _WIN32
file->file = fopen(c_str, mode);
#else
diff --git a/src/util/file/util.c b/src/util/file/util.c
index e893de7..fe7785f 100644
--- a/src/util/file/util.c
+++ b/src/util/file/util.c
@@ -23,3 +23,13 @@ s32 aki_file_read_as_c_str(struct aki_file *file, char **out)
(*out)[size] = '\n';
return size;
}
+
+s32 aki_file_replace(struct aki_file *file, str *buf)
+{
+ if (aki_file_seek(file, 0, SEEK_SET) == (off_t)-1 ||
+ !aki_file_write(file, buf->data, buf->len) ||
+ !aki_file_truncate(file, buf->len)) {
+ return -1;
+ }
+ return buf->len;
+}
diff --git a/src/util/packet.c b/src/util/packet.c
index 9e5a8d7..2d8b440 100644
--- a/src/util/packet.c
+++ b/src/util/packet.c
@@ -52,12 +52,18 @@ DEFINE_PACKET_WRITE_FUNC(s64)
DEFINE_PACKET_WRITE_FUNC(f32)
DEFINE_PACKET_WRITE_FUNC(f64)
-void aki_packet_write_string(struct aki_packet *packet, str *s)
+void aki_packet_write_str(struct aki_packet *packet, str *s)
{
AKI_PACKET_WRITE_TYPE(packet, u32, s->len);
AKI_PACKET_WRITE_DATA(packet, s->data, s->len);
}
+void aki_packet_write_wstr(struct aki_packet *packet, wstr *w)
+{
+ AKI_PACKET_WRITE_TYPE(packet, u32, w->len);
+ AKI_PACKET_WRITE_DATA(packet, w->data, w->len * sizeof(wchar_t));
+}
+
void aki_packet_write_buffer(struct aki_packet *packet, struct aki_buffer *buf)
{
AKI_PACKET_WRITE_TYPE(packet, size_t, buf->size);
@@ -83,13 +89,20 @@ DEFINE_PACKET_READ_FUNC(s64)
DEFINE_PACKET_READ_FUNC(f32)
DEFINE_PACKET_READ_FUNC(f64)
-void aki_packet_read_string(struct aki_packet *packet, str *s)
+void aki_packet_read_str(struct aki_packet *packet, str *s)
{
AKI_PACKET_READ_TYPE(packet, u32, s->len);
AKI_PACKET_READ_DATA(packet, s->len, s->data);
s->alloc = 0;
}
+void aki_packet_read_wstr(struct aki_packet *packet, wstr *w)
+{
+ AKI_PACKET_READ_TYPE(packet, u32, w->len);
+ AKI_PACKET_READ_DATA(packet, w->len * sizeof(wchar_t), w->data);
+ w->alloc = 0;
+}
+
void aki_packet_read_buffer(struct aki_packet *packet, struct aki_buffer *buf)
{
AKI_PACKET_READ_TYPE(packet, size_t, buf->size);
diff --git a/src/util/packet.h b/src/util/packet.h
index 14acf68..c6b4235 100644
--- a/src/util/packet.h
+++ b/src/util/packet.h
@@ -2,6 +2,7 @@
#include <al/types.h>
#include <al/str.h>
+#include <al/wstr.h>
#include <al/array.h>
#include "../util/buffer.h"
@@ -47,7 +48,8 @@ void aki_packet_write_u32(struct aki_packet *packet, u32 v);
void aki_packet_write_s64(struct aki_packet *packet, s64 v);
void aki_packet_write_u64(struct aki_packet *packet, u64 v);
void aki_packet_write_f32(struct aki_packet *packet, f32 v);
-void aki_packet_write_string(struct aki_packet *packet, str *s);
+void aki_packet_write_str(struct aki_packet *packet, str *s);
+void aki_packet_write_wstr(struct aki_packet *packet, wstr *w);
void aki_packet_write_buffer(struct aki_packet *packet, struct aki_buffer *buf);
s8 aki_packet_read_s8(struct aki_packet *packet);
@@ -59,7 +61,8 @@ u32 aki_packet_read_u32(struct aki_packet *packet);
s64 aki_packet_read_s64(struct aki_packet *packet);
u64 aki_packet_read_u64(struct aki_packet *packet);
f32 aki_packet_read_f32(struct aki_packet *packet);
-void aki_packet_read_string(struct aki_packet *packet, str *s);
+void aki_packet_read_str(struct aki_packet *packet, str *s);
+void aki_packet_read_wstr(struct aki_packet *packet, wstr *w);
void aki_packet_read_buffer(struct aki_packet *packet, struct aki_buffer *buf);
void aki_packet_free(struct aki_packet *packet);