sendqueue_length no longer determines if we check for socket-can-write, but sendpacket() sets a timestamp if it happened

network.*:
- sendpacket(): checks result and on EAGAIN, stores time of this event
- networking_wait_prepare(): uses the time if set to check up to 500ms later for the socket to be writeable again
- networking_wait_cleanup(): clears the time if the socket was writeable
- fixed some accidental tabs

Messenger.*, tox.*:
- pass-through functions to reach networking_wait_cleanup()
- fixed some accidental tabs
This commit is contained in:
Coren[m] 2013-10-06 16:37:02 +02:00
parent 1331a32223
commit 355c55f745
7 changed files with 79 additions and 22 deletions

View File

@ -1394,14 +1394,19 @@ void doMessenger(Messenger *m)
*/
int waitprepareMessenger(Messenger *m, uint8_t *data, uint16_t *lenptr)
{
return networking_wait_prepare(m->net, sendqueue_total(m->net_crypto->lossless_udp), data, lenptr);
return networking_wait_prepare(m->net, sendqueue_total(m->net_crypto->lossless_udp), data, lenptr);
}
int waitexecuteMessenger(Messenger *m, uint8_t *data, uint16_t len, uint16_t milliseconds)
{
return networking_wait_execute(data, len, milliseconds);
return networking_wait_execute(data, len, milliseconds);
};
void waitcleanupMessenger(Messenger *m, uint8_t *data, uint16_t len)
{
networking_wait_cleanup(m->net, data, len);
}
/* return size of the messenger data (for saving) */
uint32_t Messenger_size_old(Messenger *m)
{

View File

@ -460,6 +460,7 @@ void doMessenger(Messenger *m);
*/
int waitprepareMessenger(Messenger *m, uint8_t *data, uint16_t *lenptr);
int waitexecuteMessenger(Messenger *m, uint8_t *data, uint16_t len, uint16_t milliseconds);
void waitcleanupMessenger(Messenger *m, uint8_t *data, uint16_t len);
/* SAVING AND LOADING FUNCTIONS: */

View File

@ -209,6 +209,12 @@ int sendpacket(Networking_Core *net, IP_Port ip_port, uint8_t *data, uint32_t le
#ifdef LOGGING
loglogdata("O=>", data, length, &ip_port, res);
#endif
if (res == length)
net->send_fail_eagain = 0;
else if ((res < 0) && (errno == EAGAIN))
net->send_fail_eagain = current_time();
return res;
}
@ -308,24 +314,28 @@ void networking_poll(Networking_Core *net)
*/
typedef struct
{
sock_t sock;
uint32_t sendqueue_length;
sock_t sock;
uint32_t sendqueue_length;
uint16_t send_fail_reset;
uint64_t send_fail_eagain;
} select_info;
int networking_wait_prepare(Networking_Core *net, uint32_t sendqueue_length, uint8_t *data, uint16_t *lenptr)
{
if ((data == NULL) || (*lenptr < sizeof(select_info)))
{
*lenptr = sizeof(select_info);
return 0;
}
if ((data == NULL) || (*lenptr < sizeof(select_info)))
{
*lenptr = sizeof(select_info);
return 0;
}
*lenptr = sizeof(select_info);
select_info *s = (select_info *)data;
s->sock = net->sock;
s->sendqueue_length = sendqueue_length;
*lenptr = sizeof(select_info);
select_info *s = (select_info *)data;
s->sock = net->sock;
s->sendqueue_length = sendqueue_length;
s->send_fail_reset = 0;
s->send_fail_eagain = net->send_fail_eagain;
return 1;
return 1;
}
int networking_wait_execute(uint8_t *data, uint16_t len, uint16_t milliseconds)
@ -333,9 +343,23 @@ int networking_wait_execute(uint8_t *data, uint16_t len, uint16_t milliseconds)
/* WIN32: supported since Win2K, but might need some adjustements */
/* UNIX: this should work for any remotely Unix'ish system */
select_info *s = (select_info *)data;
select_info *s = (select_info *)data;
int nfds = 1 + s->sock;
/* add only if we had a failed write */
int writefds_add = 0;
if (s->send_fail_eagain != 0)
{
// current_time(): microseconds
uint64_t now = current_time();
/* 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
* fast link, but too short for a sloooooow link... */
if (now - s->send_fail_eagain < 500000)
writefds_add = 1;
}
int nfds = 1 + s->sock;
/* the FD_ZERO calls might be superfluous */
fd_set readfds;
@ -344,8 +368,7 @@ int networking_wait_execute(uint8_t *data, uint16_t len, uint16_t milliseconds)
fd_set writefds;
FD_ZERO(&writefds);
/* add only if we have packets queued, signals that a write won't block */
if (s->sendqueue_length > 0)
if (writefds_add)
FD_SET(s->sock, &writefds);
fd_set exceptfds;
@ -368,9 +391,19 @@ int networking_wait_execute(uint8_t *data, uint16_t len, uint16_t milliseconds)
loglog(logbuffer);
#endif
if (FD_ISSET(s->sock, &writefds))
s->send_fail_reset = 1;
return res > 0 ? 1 : 0;
};
void networking_wait_cleanup(Networking_Core *net, uint8_t *data, uint16_t len)
{
select_info *s = (select_info *)data;
if (s->send_fail_reset)
net->send_fail_eagain = 0;
}
uint8_t at_startup_ran = 0;
static int at_startup(void)
{
@ -996,10 +1029,10 @@ int addr_resolve_or_parse_ip(const char *address, IP *to, IP *extra)
static char errmsg_ok[3] = "OK";
static void loglogdata(char *message, uint8_t *buffer, size_t buflen, IP_Port *ip_port, ssize_t res)
{
uint16_t port = ntohs(ip_port->port);
uint32_t data[2];
data[0] = buflen > 4 ? ntohl(*(uint32_t *)&buffer[1]) : 0;
data[1] = buflen > 7 ? ntohl(*(uint32_t *)&buffer[5]) : 0;
uint16_t port = ntohs(ip_port->port);
uint32_t data[2];
data[0] = buflen > 4 ? ntohl(*(uint32_t *)&buffer[1]) : 0;
data[1] = buflen > 7 ? ntohl(*(uint32_t *)&buffer[5]) : 0;
if (res < 0)
{
int written = snprintf(logbuffer, sizeof(logbuffer), "[%2u] %s %3hu%c %s:%hu (%u: %s) | %04x%04x\n",

View File

@ -244,6 +244,7 @@ typedef struct {
sa_family_t family;
uint16_t port;
sock_t sock;
uint64_t send_fail_eagain;
} Networking_Core;
/* return current time in milleseconds since the epoch. */
@ -269,6 +270,7 @@ void networking_poll(Networking_Core *net);
*/
int networking_wait_prepare(Networking_Core *net, uint32_t sendqueue_length, uint8_t *data, uint16_t *lenptr);
int networking_wait_execute(uint8_t *data, uint16_t len, uint16_t milliseconds);
void networking_wait_cleanup(Networking_Core *net, uint8_t *data, uint16_t len);
/* Initialize networking.
* bind to ip and port.

View File

@ -551,6 +551,12 @@ int tox_wait_execute(Tox *tox, uint8_t *data, uint16_t len, uint16_t millisecond
waitexecuteMessenger(m, data, len, milliseconds);
}
void tox_wait_cleanup(Tox *tox, uint8_t *data, uint16_t len)
{
Messenger *m = tox;
waitcleanupMessenger(m, data, len);
}
/* SAVING AND LOADING FUNCTIONS: */
/* return size of the messenger data (for saving). */

View File

@ -491,6 +491,7 @@ void tox_do(Tox *tox);
* returns 1 on success
* returns 0 on failure (length is insufficient)
*
*
* tox_wait_execute(): function can be called asynchronously
* Waits for something to happen on the socket for up to milliseconds milliseconds.
* *** Function MUSTN'T poll. ***
@ -501,9 +502,17 @@ void tox_do(Tox *tox);
* returns 0 if the timeout was reached
* returns -1 if data was NULL or len too short
*
*
* tox_wait_cleanup(): function should be called under lock
* Stores results from tox_wait_execute().
*
* data[]/len shall be the exact same as given to tox_wait_execute()
*
*/
int tox_wait_prepare(Tox *tox, uint8_t *data, uint16_t *lenptr);
int tox_wait_execute(Tox *tox, uint8_t *data, uint16_t len, uint16_t milliseconds);
void tox_wait_cleanup(Tox *tox, uint8_t *data, uint16_t len);
/* SAVING AND LOADING FUNCTIONS: */

View File

@ -20,6 +20,7 @@ typedef int (*load_state_callback_func)(void *outer, uint8_t *data, uint32_t len
int load_state(load_state_callback_func load_state_callback, void *outer,
uint8_t *data, uint32_t length, uint16_t cookie_inner);
#define LOGGING
#ifdef LOGGING
extern char logbuffer[512];
void loginit(uint16_t port);