Skip to content

Commit

Permalink
Merge pull request #45 from Anotra/io_poller
Browse files Browse the repository at this point in the history
  • Loading branch information
lcsmuller authored Mar 13, 2022
2 parents 5e65922 + a85e7d8 commit aa40e93
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 25 deletions.
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

0 comments on commit aa40e93

Please sign in to comment.