mirror of
https://github.com/irungentoo/toxcore.git
synced 2024-03-22 13:30:51 +08:00
Some tox_wait_* improvements
This commit is contained in:
parent
199f083e0a
commit
e118319467
|
@ -2342,19 +2342,24 @@ void do_messenger(Messenger *m)
|
||||||
/*
|
/*
|
||||||
* functions to avoid excessive polling
|
* functions to avoid excessive polling
|
||||||
*/
|
*/
|
||||||
int wait_prepare_messenger(Messenger *m, uint8_t *data, uint16_t *lenptr)
|
size_t wait_data_size()
|
||||||
{
|
{
|
||||||
return networking_wait_prepare(m->net, sendqueue_total(m->net_crypto->lossless_udp), data, lenptr);
|
return networking_wait_data_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
int wait_execute_messenger(Messenger *m, uint8_t *data, uint16_t len, uint16_t milliseconds)
|
int wait_prepare_messenger(Messenger *m, uint8_t *data)
|
||||||
{
|
{
|
||||||
return networking_wait_execute(data, len, milliseconds);
|
return networking_wait_prepare(m->net, sendqueue_total(m->net_crypto->lossless_udp), data);
|
||||||
};
|
}
|
||||||
|
|
||||||
void wait_cleanup_messenger(Messenger *m, uint8_t *data, uint16_t len)
|
int wait_execute_messenger(uint8_t *data, long seconds, long microseconds)
|
||||||
{
|
{
|
||||||
networking_wait_cleanup(m->net, data, len);
|
return networking_wait_execute(data, seconds, microseconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
int wait_cleanup_messenger(Messenger *m, uint8_t *data)
|
||||||
|
{
|
||||||
|
return networking_wait_cleanup(m->net, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* new messenger format for load/save, more robust and forward compatible */
|
/* new messenger format for load/save, more robust and forward compatible */
|
||||||
|
|
|
@ -715,9 +715,10 @@ void do_messenger(Messenger *m);
|
||||||
/*
|
/*
|
||||||
* functions to avoid excessive polling
|
* functions to avoid excessive polling
|
||||||
*/
|
*/
|
||||||
int wait_prepare_messenger(Messenger *m, uint8_t *data, uint16_t *lenptr);
|
size_t wait_data_size();
|
||||||
int wait_execute_messenger(Messenger *m, uint8_t *data, uint16_t len, uint16_t milliseconds);
|
int wait_prepare_messenger(Messenger *m, uint8_t *data);
|
||||||
void wait_cleanup_messenger(Messenger *m, uint8_t *data, uint16_t len);
|
int wait_execute_messenger(uint8_t *data, long seconds, long microseconds);
|
||||||
|
int wait_cleanup_messenger(Messenger *m, uint8_t *data);
|
||||||
|
|
||||||
/* SAVING AND LOADING FUNCTIONS: */
|
/* SAVING AND LOADING FUNCTIONS: */
|
||||||
|
|
||||||
|
|
|
@ -315,17 +315,17 @@ typedef struct {
|
||||||
uint64_t send_fail_eagain;
|
uint64_t send_fail_eagain;
|
||||||
} select_info;
|
} select_info;
|
||||||
|
|
||||||
int networking_wait_prepare(Networking_Core *net, uint32_t sendqueue_length, uint8_t *data, uint16_t *lenptr)
|
size_t networking_wait_data_size()
|
||||||
{
|
{
|
||||||
if ((data == NULL) || !lenptr || (*lenptr < sizeof(select_info))) {
|
return sizeof(select_info);
|
||||||
if (lenptr) {
|
}
|
||||||
*lenptr = sizeof(select_info);
|
|
||||||
return 0;
|
int networking_wait_prepare(Networking_Core *net, uint32_t sendqueue_length, uint8_t *data)
|
||||||
} else
|
{
|
||||||
return -1;
|
if (data == NULL) {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
*lenptr = sizeof(select_info);
|
|
||||||
select_info *s = (select_info *)data;
|
select_info *s = (select_info *)data;
|
||||||
s->sock = net->sock;
|
s->sock = net->sock;
|
||||||
s->sendqueue_length = sendqueue_length;
|
s->sendqueue_length = sendqueue_length;
|
||||||
|
@ -335,26 +335,42 @@ int networking_wait_prepare(Networking_Core *net, uint32_t sendqueue_length, uin
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int networking_wait_execute(uint8_t *data, uint16_t len, uint16_t milliseconds)
|
/* *** Function MUSTN'T poll. ***
|
||||||
|
* The function mustn't modify anything at all, so it can be called completely
|
||||||
|
* asynchronously without any worry.
|
||||||
|
*/
|
||||||
|
int networking_wait_execute(uint8_t *data, long seconds, long microseconds)
|
||||||
{
|
{
|
||||||
/* WIN32: supported since Win2K, but might need some adjustements */
|
/* WIN32: supported since Win2K, but might need some adjustements */
|
||||||
/* UNIX: this should work for any remotely Unix'ish system */
|
/* UNIX: this should work for any remotely Unix'ish system */
|
||||||
|
|
||||||
|
if (data == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
select_info *s = (select_info *)data;
|
select_info *s = (select_info *)data;
|
||||||
|
|
||||||
/* add only if we had a failed write */
|
/* add only if we had a failed write */
|
||||||
int writefds_add = 0;
|
int writefds_add = 0;
|
||||||
|
|
||||||
|
/* if send_fail_eagain is set, that means that socket's buffer was full and couldn't fit data we tried to send,
|
||||||
|
* so this is the only case when we need to know when the socket becomes write-ready, i.e. socket's buffer gets
|
||||||
|
* some free space for us to put data to be sent in, but select will tell us that the socket is writable even
|
||||||
|
* if we can fit a small part of our data (say 1 byte), so we wait some time, in hope that large enough chunk
|
||||||
|
* of socket's buffer will be available (at least that's how I understand intentions of the previous author of
|
||||||
|
* that code)
|
||||||
|
*/
|
||||||
if (s->send_fail_eagain != 0) {
|
if (s->send_fail_eagain != 0) {
|
||||||
// current_time(): microseconds
|
// current_time(): microseconds
|
||||||
uint64_t now = current_time();
|
uint64_t now = current_time();
|
||||||
|
|
||||||
/* s->sendqueue_length: might be used to guess how long we keep checking */
|
/* s->sendqueue_length: might be used to guess how long we keep checking */
|
||||||
/* for now, threshold is hardcoded to 500ms, too long for a really really
|
/* for now, threshold is hardcoded to 250ms, too long for a really really
|
||||||
* fast link, but too short for a sloooooow link... */
|
* fast link, but too short for a sloooooow link... */
|
||||||
if (now - s->send_fail_eagain < 500000)
|
if (now - s->send_fail_eagain < 250000) {
|
||||||
writefds_add = 1;
|
writefds_add = 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int nfds = 1 + s->sock;
|
int nfds = 1 + s->sock;
|
||||||
|
|
||||||
|
@ -366,27 +382,34 @@ int networking_wait_execute(uint8_t *data, uint16_t len, uint16_t milliseconds)
|
||||||
fd_set writefds;
|
fd_set writefds;
|
||||||
FD_ZERO(&writefds);
|
FD_ZERO(&writefds);
|
||||||
|
|
||||||
if (writefds_add)
|
if (writefds_add) {
|
||||||
FD_SET(s->sock, &writefds);
|
FD_SET(s->sock, &writefds);
|
||||||
|
}
|
||||||
|
|
||||||
fd_set exceptfds;
|
fd_set exceptfds;
|
||||||
FD_ZERO(&exceptfds);
|
FD_ZERO(&exceptfds);
|
||||||
FD_SET(s->sock, &exceptfds);
|
FD_SET(s->sock, &exceptfds);
|
||||||
|
|
||||||
struct timeval timeout;
|
struct timeval timeout;
|
||||||
timeout.tv_sec = 0;
|
struct timeval *timeout_ptr = &timeout;
|
||||||
timeout.tv_usec = milliseconds * 1000;
|
|
||||||
|
if (seconds < 0 || microseconds < 0) {
|
||||||
|
timeout_ptr = NULL;
|
||||||
|
} else {
|
||||||
|
timeout.tv_sec = seconds;
|
||||||
|
timeout.tv_usec = microseconds;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef LOGGING
|
#ifdef LOGGING
|
||||||
errno = 0;
|
errno = 0;
|
||||||
#endif
|
#endif
|
||||||
/* returns -1 on error, 0 on timeout, the socket on activity */
|
/* returns -1 on error, 0 on timeout, the socket on activity */
|
||||||
int res = select(nfds, &readfds, &writefds, &exceptfds, &timeout);
|
int res = select(nfds, &readfds, &writefds, &exceptfds, timeout_ptr);
|
||||||
#ifdef LOGGING
|
#ifdef LOGGING
|
||||||
|
|
||||||
/* only dump if not timeout */
|
/* only dump if not timeout */
|
||||||
if (res) {
|
if (res) {
|
||||||
sprintf(logbuffer, "select(%d): %d (%d, %s) - %d %d %d\n", milliseconds, res, errno,
|
sprintf(logbuffer, "select(%d, %d): %d (%d, %s) - %d %d %d\n", microseconds, seconds, res, errno,
|
||||||
strerror(errno), FD_ISSET(s->sock, &readfds), FD_ISSET(s->sock, &writefds),
|
strerror(errno), FD_ISSET(s->sock, &readfds), FD_ISSET(s->sock, &writefds),
|
||||||
FD_ISSET(s->sock, &exceptfds));
|
FD_ISSET(s->sock, &exceptfds));
|
||||||
loglog(logbuffer);
|
loglog(logbuffer);
|
||||||
|
@ -394,20 +417,28 @@ int networking_wait_execute(uint8_t *data, uint16_t len, uint16_t milliseconds)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (FD_ISSET(s->sock, &writefds))
|
if (FD_ISSET(s->sock, &writefds)) {
|
||||||
s->send_fail_reset = 1;
|
s->send_fail_reset = 1;
|
||||||
|
|
||||||
return res > 0 ? 1 : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void networking_wait_cleanup(Networking_Core *net, uint8_t *data, uint16_t len)
|
return res > 0 ? 2 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int networking_wait_cleanup(Networking_Core *net, uint8_t *data)
|
||||||
{
|
{
|
||||||
|
if (data == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
select_info *s = (select_info *)data;
|
select_info *s = (select_info *)data;
|
||||||
|
|
||||||
if (s->send_fail_reset)
|
if (s->send_fail_reset) {
|
||||||
net->send_fail_eagain = 0;
|
net->send_fail_eagain = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t at_startup_ran = 0;
|
uint8_t at_startup_ran = 0;
|
||||||
static int at_startup(void)
|
static int at_startup(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -312,9 +312,10 @@ void networking_poll(Networking_Core *net);
|
||||||
/*
|
/*
|
||||||
* functions to avoid excessive polling
|
* functions to avoid excessive polling
|
||||||
*/
|
*/
|
||||||
int networking_wait_prepare(Networking_Core *net, uint32_t sendqueue_length, uint8_t *data, uint16_t *lenptr);
|
size_t networking_wait_data_size();
|
||||||
int networking_wait_execute(uint8_t *data, uint16_t len, uint16_t milliseconds);
|
int networking_wait_prepare(Networking_Core *net, uint32_t sendqueue_length, uint8_t *data);
|
||||||
void networking_wait_cleanup(Networking_Core *net, uint8_t *data, uint16_t len);
|
int networking_wait_execute(uint8_t *data, long seconds, long microseconds);
|
||||||
|
int networking_wait_cleanup(Networking_Core *net, uint8_t *data);
|
||||||
|
|
||||||
/* Initialize networking.
|
/* Initialize networking.
|
||||||
* bind to ip and port.
|
* bind to ip and port.
|
||||||
|
|
|
@ -767,22 +767,27 @@ void tox_do(Tox *tox)
|
||||||
/*
|
/*
|
||||||
* functions to avoid excessive polling
|
* functions to avoid excessive polling
|
||||||
*/
|
*/
|
||||||
int tox_wait_prepare(Tox *tox, uint8_t *data, uint16_t *lenptr)
|
|
||||||
|
size_t tox_wait_data_size()
|
||||||
{
|
{
|
||||||
Messenger *m = tox;
|
return wait_data_size();
|
||||||
return wait_prepare_messenger(m, data, lenptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int tox_wait_execute(Tox *tox, uint8_t *data, uint16_t len, uint16_t milliseconds)
|
int tox_wait_prepare(Tox *tox, uint8_t *data)
|
||||||
{
|
{
|
||||||
Messenger *m = tox;
|
Messenger *m = tox;
|
||||||
return wait_execute_messenger(m, data, len, milliseconds);
|
return wait_prepare_messenger(m, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tox_wait_cleanup(Tox *tox, uint8_t *data, uint16_t len)
|
int tox_wait_execute(uint8_t *data, long seconds, long microseconds)
|
||||||
|
{
|
||||||
|
return wait_execute_messenger(data, seconds, microseconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
int tox_wait_cleanup(Tox *tox, uint8_t *data)
|
||||||
{
|
{
|
||||||
Messenger *m = tox;
|
Messenger *m = tox;
|
||||||
wait_cleanup_messenger(m, data, len);
|
return wait_cleanup_messenger(m, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SAVING AND LOADING FUNCTIONS: */
|
/* SAVING AND LOADING FUNCTIONS: */
|
||||||
|
|
|
@ -662,37 +662,43 @@ void tox_kill(Tox *tox);
|
||||||
void tox_do(Tox *tox);
|
void tox_do(Tox *tox);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* tox_wait_prepare(): function should be called under lock
|
* tox_wait_data_size():
|
||||||
|
*
|
||||||
|
* returns a size of data buffer to allocate. the size is constant.
|
||||||
|
*
|
||||||
|
* tox_wait_prepare(): function should be called under lock every time we want to call tox_wait_execute()
|
||||||
* Prepares the data required to call tox_wait_execute() asynchronously
|
* Prepares the data required to call tox_wait_execute() asynchronously
|
||||||
*
|
*
|
||||||
* data[] is reserved and kept by the caller
|
* data[] should be of at least tox_wait_data_size() size and it's reserved and kept by the caller
|
||||||
* *lenptr is in/out: in = reserved data[], out = required data[]
|
* Use that data[] to call tox_wait_execute()
|
||||||
*
|
*
|
||||||
* returns 1 on success
|
* returns 1 on success
|
||||||
* returns 0 if *lenptr is insufficient
|
* returns 0 if data was NULL
|
||||||
* returns -1 if lenptr is NULL
|
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* tox_wait_execute(): function can be called asynchronously
|
* tox_wait_execute(): function can be called asynchronously
|
||||||
* Waits for something to happen on the socket for up to milliseconds milliseconds.
|
* Waits for something to happen on the socket for up to seconds seconds and mircoseconds microseconds.
|
||||||
* *** Function MUSTN'T poll. ***
|
* mircoseconds should be between 0 and 999999.
|
||||||
* The function mustn't modify anything at all, so it can be called completely
|
* If you set either or both seconds and microseconds to negatives, it will block indefinetly until there
|
||||||
* asynchronously without any worry.
|
* is an activity.
|
||||||
*
|
*
|
||||||
* returns 1 if there is socket activity (i.e. tox_do() should be called)
|
* returns 2 if there is socket activity (i.e. tox_do() should be called)
|
||||||
* returns 0 if the timeout was reached
|
* returns 1 if the timeout was reached (tox_do() should be called anyway. it's advised to call it at least
|
||||||
* returns -1 if data was NULL or len too short
|
* once per second)
|
||||||
|
* returns 0 if data was NULL
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* tox_wait_cleanup(): function should be called under lock
|
* tox_wait_cleanup(): function should be called under lock, every time tox_wait_execute() finishes
|
||||||
* Stores results from tox_wait_execute().
|
* Stores results from tox_wait_execute().
|
||||||
*
|
*
|
||||||
* data[]/len shall be the exact same as given to tox_wait_execute()
|
* returns 1 on success
|
||||||
|
* returns 0 if data was NULL
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int tox_wait_prepare(Tox *tox, uint8_t *data, uint16_t *lenptr);
|
size_t tox_wait_data_size();
|
||||||
int tox_wait_execute(Tox *tox, uint8_t *data, uint16_t len, uint16_t milliseconds);
|
int tox_wait_prepare(Tox *tox, uint8_t *data);
|
||||||
void tox_wait_cleanup(Tox *tox, uint8_t *data, uint16_t len);
|
int tox_wait_execute(uint8_t *data, long seconds, long microseconds);
|
||||||
|
int tox_wait_cleanup(Tox *tox, uint8_t *data);
|
||||||
|
|
||||||
|
|
||||||
/* SAVING AND LOADING FUNCTIONS: */
|
/* SAVING AND LOADING FUNCTIONS: */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user