Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

io_poller docs, and features. #45

Merged
merged 5 commits into from
Mar 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 30 additions & 15 deletions core/io_poller.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ io_poller_perform(struct io_poller *io)
events |= IO_POLLER_OUT;
io->pollfds[i].revents = 0;
struct io_poller_element *element = &io->elements[i];
element->cb(element->user_data, events);
element->cb(io, events, element->user_data);
}
}
for (int i = 0; i < io->curlm_cnt; i++) {
Expand All @@ -108,7 +108,7 @@ io_poller_perform(struct io_poller *io)
(-1 != curlm->timeout && now >= curlm->timeout)) {
curlm->should_perform = false;
int result = curlm->cb ?
curlm->cb(curlm->multi, curlm->user_data) :
curlm->cb(io, curlm->multi, curlm->user_data) :
curl_multi_socket_all(curlm->multi, &curlm->running);

if (result != 0)
Expand All @@ -119,8 +119,11 @@ io_poller_perform(struct io_poller *io)
}

bool
io_poller_socket_add(
struct io_poller *io, io_poller_socket fd, enum io_poller_events events, io_poller_cb cb, void *user_data)
io_poller_socket_add(struct io_poller *io,
io_poller_socket fd,
enum io_poller_events events,
io_poller_cb cb,
void *user_data)
{
int index = 0;
for (; index < io->cnt; index++)
Expand Down Expand Up @@ -180,8 +183,9 @@ io_poller_socket_del(struct io_poller *io, io_poller_socket fd)
}

static void
io_curl_cb(void *user_data, enum io_poller_events events)
io_curl_cb(struct io_poller *io, enum io_poller_events events, void *user_data)
{
(void)io;
(void)events;
struct io_curlm *io_curlm = user_data;
io_curlm->should_perform = true;
Expand Down Expand Up @@ -257,28 +261,39 @@ io_poller_curlm_add(struct io_poller *io,
CURLM *multi,
io_poller_curl_cb cb,
void *user_data)
{
struct io_curlm *io_curlm = calloc(1, sizeof *io_curlm);
io_curlm->io_poller = io;
io_curlm->cb = cb;
io_curlm->multi = multi;
io_curlm->user_data = user_data;
io_curlm->timeout = -1;
io_curlm->should_perform = true;

{
struct io_curlm *io_curlm = NULL;
size_t index = 0;
for (; index < io->curlm_cnt; index++) {
if (io->curlm[index]->multi == multi) {
io_curlm = io->curlm[index];
goto modify;
}
}
if (io->curlm_cnt == io->curlm_cap) {
size_t cap = io->curlm_cap << 1;
if (!cap) cap = 8;
void *tmp = realloc(io->curlm, cap * sizeof *io->curlm);
if (!tmp) return free(io_curlm), false;
if (!tmp) return false;
io->curlm = tmp;
io->curlm_cap = cap;
}

if (!(io_curlm = calloc(1, sizeof *io_curlm)))
return false;
io->curlm[io->curlm_cnt++] = io_curlm;
io_curlm->io_poller = io;
io_curlm->multi = multi;
io_curlm->timeout = -1;
io_curlm->should_perform = true;
curl_multi_setopt(multi, CURLMOPT_TIMERFUNCTION, curl_timer_cb);
curl_multi_setopt(multi, CURLMOPT_TIMERDATA, io_curlm);
curl_multi_setopt(multi, CURLMOPT_SOCKETFUNCTION, curl_socket_cb);
curl_multi_setopt(multi, CURLMOPT_SOCKETDATA, io_curlm);

modify:
io_curlm->cb = cb;
io_curlm->user_data = user_data;
return true;
}

Expand Down
89 changes: 81 additions & 8 deletions core/io_poller.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,107 @@
#include <stdbool.h>
#include <curl/curl.h>

/**
* @brief The flags to poll for
*/
enum io_poller_events {
IO_POLLER_IN = 1,
IO_POLLER_OUT = 2,
IO_POLLER_IN = 1 << 0,
IO_POLLER_OUT = 1 << 1,
};

/**
* @brief a socket or file descriptor
*/
typedef int io_poller_socket;

/**
* @brief handle for watching file descriptors, sockets, and curl multis
*/
struct io_poller;
typedef void (*io_poller_cb)(void *user_data, enum io_poller_events events);

/**
* @brief callback for when an event is triggered by the socket
*/
typedef void (*io_poller_cb)(struct io_poller *io,
enum io_poller_events events,
void *user_data);

struct io_poller *io_poller_create(void);
void io_poller_destroy(struct io_poller *io);

/**
* @brief wait for events to be triggered
* @param io the io_poller to poll on
* @param milliseconds -1 for infinity, or ms to poll for
* @return -1 for error, or number of sockets that have events waiting
*/
int io_poller_poll(struct io_poller *io, int milliseconds);

/**
* @brief performs any actions needed and clears events set by io_poller_poll
* @param io the io_poller to perform on
* @return 0 on success
*/
int io_poller_perform(struct io_poller *io);

/**
* @brief adds or modifies a socket or file descriptor to watch list
* @param io the io_poller to add socket to
* @param sock the file descriptor or socket to handle
* @param events the events to watch for
* @param cb the callback for when any event is triggered
* @param user_data custom user data
* @return true on success
*/
bool io_poller_socket_add(struct io_poller *io,
io_poller_socket sock,
enum io_poller_events events,
io_poller_cb cb,
void *user_data);
io_poller_socket sock,
enum io_poller_events events,
io_poller_cb cb,
void *user_data);

/**
* @brief removes a socket or file descriptor from watch list
* @param io the io_poller to remove the socket from
* @param sock the file descriptor or socket to remove
* @return true on success
*/
bool io_poller_socket_del(struct io_poller *io, io_poller_socket sock);

typedef int (*io_poller_curl_cb)(CURLM *multi, void *user_data);
/**
* @brief callback for when curl multi should be performed on
*/
typedef int (*io_poller_curl_cb)(struct io_poller *io,
CURLM *multi,
void *user_data);

/**
* @brief add or modifies a curl multi to watch list
* @param io the io_poller to add curl multi to
* @param multi the curl multi to add or modify
* @param cb the callback for when curl multi should be performed on
* @param user_data custom user data
* @return true on success
*/
bool io_poller_curlm_add(struct io_poller *io,
CURLM *multi,
io_poller_curl_cb cb,
void *user_data);

/**
* @brief remove curl multi from watch list
* @param io the io_poller to remove curl multi from
* @param multi the curl multi to remove
* @return true on success
*/
bool io_poller_curlm_del(struct io_poller *io, CURLM *multi);

/**
* @brief this multi should be performed on next cycle
* causing poll to return immediately
* @param io the io_poller to enable perform on
* @param multi the multi that should be performed
* @return true on success
*/
bool io_poller_curlm_enable_perform(struct io_poller *io, CURLM *multi);

#endif // CONCORD_IO_POLLER_H
9 changes: 9 additions & 0 deletions include/discord.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "error.h"
#include "types.h"
#include "concord-once.h"
#include "io_poller.h"

#define DISCORD_API_BASE_URL "https://discord.com/api/v9"
#define DISCORD_GATEWAY_URL_SUFFIX "?v=9&encoding=json"
Expand Down Expand Up @@ -265,6 +266,14 @@ uint64_t discord_timestamp(struct discord *client);
*/
struct logconf *discord_get_logconf(struct discord *client);

/**
* @brief get the io_poller used by the discord client
*
* @param client the client created with discord_init()
* @return struct io_poller*
*/
struct io_poller *discord_get_io_poller(struct discord *client);

/** @} Discord */

#endif /* DISCORD_H */
3 changes: 2 additions & 1 deletion src/discord-adapter.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ setopt_cb(struct ua_conn *conn, void *p_token)
}

static int
on_io_poller_curl(CURLM *mhandle, void *user_data)
on_io_poller_curl(struct io_poller *io, CURLM *mhandle, void *user_data)
{
(void)io;
(void)mhandle;
return discord_adapter_perform(user_data);
}
Expand Down
6 changes: 6 additions & 0 deletions src/discord-client.c
Original file line number Diff line number Diff line change
Expand Up @@ -690,3 +690,9 @@ discord_get_logconf(struct discord *client)
{
return &client->conf;
}

struct io_poller *
discord_get_io_poller(struct discord *client)
{
return client->io_poller;
}
3 changes: 2 additions & 1 deletion src/discord-gateway.c
Original file line number Diff line number Diff line change
Expand Up @@ -1460,8 +1460,9 @@ default_scheduler_cb(struct discord *a,
}

static int
on_io_poller_curl(CURLM *mhandle, void *user_data)
on_io_poller_curl(struct io_poller *io, CURLM *mhandle, void *user_data)
{
(void)io;
(void)mhandle;
return discord_gateway_perform(user_data);
}
Expand Down