From 0a4c3d7e2e080dafd66d25f7a5806b89f7be1bcf Mon Sep 17 00:00:00 2001 From: "Coren[m]" Date: Thu, 24 Oct 2013 22:32:28 +0200 Subject: Move unix_time(), id_cpy()/id_eq(), is_timeout() to util.* unix_time(): - returns local value for current epoch - value is updated explicitly with unix_time_update() called at new_DHT()/doMessenger()/do_DHT() is_timeout(): - uses the local value for current epoch id_cpy()/id_eq() => id_copy()/id_equal(): - centralized duplicate definitions - replaced (most) memcpy()/memcmp() of (*, *, CLIENT_ID_SIZE) with id_copy()/id_equal() --- other/DHT_bootstrap.c | 6 +++- toxcore/DHT.c | 77 ++++++++++++++++------------------------ toxcore/LAN_discovery.c | 3 +- toxcore/Messenger.c | 28 ++++++++------- toxcore/friend_requests.c | 8 ++--- toxcore/group_chats.c | 89 ++++++++++++++++++++++------------------------- toxcore/net_crypto.c | 38 ++++++++++---------- toxcore/network.h | 3 -- toxcore/ping.c | 27 ++++++-------- toxcore/util.c | 32 +++++++++++++---- toxcore/util.h | 14 ++++++-- 11 files changed, 163 insertions(+), 162 deletions(-) diff --git a/other/DHT_bootstrap.c b/other/DHT_bootstrap.c index 4a5d937d..af5fae01 100644 --- a/other/DHT_bootstrap.c +++ b/other/DHT_bootstrap.c @@ -1,3 +1,4 @@ + /* DHT boostrap * * A simple DHT boostrap server for tox. @@ -20,6 +21,7 @@ * along with Tox. If not, see . * */ + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -27,6 +29,8 @@ #include "../toxcore/DHT.h" #include "../toxcore/LAN_discovery.h" #include "../toxcore/friend_requests.h" +#include "../toxcore/util.h" + #include "../testing/misc_tools.c" /* Sleep function (x = milliseconds) */ @@ -147,7 +151,7 @@ int main(int argc, char *argv[]) do_DHT(dht); - if (last_LANdiscovery + (is_waiting_for_dht_connection ? 5 : LAN_DISCOVERY_INTERVAL) < unix_time()) { + if (is_timeout(last_LANdiscovery, is_waiting_for_dht_connection ? 5 : LAN_DISCOVERY_INTERVAL)) { send_LANdiscovery(htons(PORT), dht->c); last_LANdiscovery = unix_time(); } diff --git a/toxcore/DHT.c b/toxcore/DHT.c index ee51f16c..c286567f 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c @@ -115,25 +115,14 @@ static int client_id_cmp(ClientPair p1, ClientPair p2) return c; } -static int id_equal(uint8_t *a, uint8_t *b) -{ - return memcmp(a, b, CLIENT_ID_SIZE) == 0; -} - -static int is_timeout(uint64_t time_now, uint64_t timestamp, uint64_t timeout) -{ - return timestamp + timeout <= time_now; -} - static int client_in_list(Client_data *list, uint32_t length, uint8_t *client_id) { uint32_t i; - uint64_t temp_time = unix_time(); for (i = 0; i < length; i++) /* Dead nodes are considered dead (not in the list)*/ - if (!is_timeout(temp_time, list[i].assoc4.timestamp, KILL_NODE_TIMEOUT) || - !is_timeout(temp_time, list[i].assoc6.timestamp, KILL_NODE_TIMEOUT)) + if (!is_timeout(list[i].assoc4.timestamp, KILL_NODE_TIMEOUT) || + !is_timeout(list[i].assoc6.timestamp, KILL_NODE_TIMEOUT)) if (id_equal(list[i].client_id, client_id)) return 1; @@ -272,7 +261,7 @@ static int friend_number(DHT *dht, uint8_t *client_id) */ static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_family_t sa_family, Client_data *client_list, uint32_t client_list_length, - time_t timestamp, int *num_nodes_ptr, uint8_t is_LAN) + int *num_nodes_ptr, uint8_t is_LAN) { if ((sa_family != AF_INET) && (sa_family != AF_INET6)) return; @@ -295,7 +284,7 @@ static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nod ipptp = &client->assoc6; /* node not in a good condition? */ - if (is_timeout(timestamp, ipptp->timestamp, BAD_NODE_TIMEOUT)) + if (is_timeout(ipptp->timestamp, BAD_NODE_TIMEOUT)) continue; IP *client_ip = &ipptp->ip_port.ip; @@ -366,15 +355,14 @@ static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nod */ static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_family_t sa_family, uint8_t is_LAN) { - time_t timestamp = unix_time(); int num_nodes = 0, i; get_close_nodes_inner(dht, client_id, nodes_list, sa_family, - dht->close_clientlist, LCLIENT_LIST, timestamp, &num_nodes, is_LAN); + dht->close_clientlist, LCLIENT_LIST, &num_nodes, is_LAN); for (i = 0; i < dht->num_friends; ++i) get_close_nodes_inner(dht, client_id, nodes_list, sa_family, dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, - timestamp, &num_nodes, is_LAN); + &num_nodes, is_LAN); return num_nodes; } @@ -393,7 +381,6 @@ static int replace_bad( Client_data *list, return 1; uint32_t i; - uint64_t temp_time = unix_time(); for (i = 0; i < length; ++i) { /* If node is bad */ @@ -405,10 +392,10 @@ static int replace_bad( Client_data *list, else ipptp = &client->assoc6; - if (is_timeout(temp_time, ipptp->timestamp, BAD_NODE_TIMEOUT)) { + if (is_timeout(ipptp->timestamp, BAD_NODE_TIMEOUT)) { memcpy(client->client_id, client_id, CLIENT_ID_SIZE); ipptp->ip_port = ip_port; - ipptp->timestamp = temp_time; + ipptp->timestamp = unix_time(); ip_reset(&ipptp->ret_ip_port.ip); ipptp->ret_ip_port.port = 0; @@ -587,10 +574,9 @@ static int is_gettingnodes(DHT *dht, IP_Port ip_port, uint64_t ping_id) { uint32_t i; uint8_t pinging; - uint64_t temp_time = unix_time(); for (i = 0; i < LSEND_NODES_ARRAY; ++i ) { - if (!is_timeout(temp_time, dht->send_nodes[i].timestamp, PING_TIMEOUT)) { + if (!is_timeout(dht->send_nodes[i].timestamp, PING_TIMEOUT)) { pinging = 0; if (ping_id != 0 && dht->send_nodes[i].id == ping_id) @@ -612,12 +598,11 @@ static uint64_t add_gettingnodes(DHT *dht, IP_Port ip_port) { uint32_t i, j; uint64_t ping_id = ((uint64_t)random_int() << 32) + random_int(); - uint64_t temp_time = unix_time(); for (i = 0; i < PING_TIMEOUT; ++i ) { for (j = 0; j < LSEND_NODES_ARRAY; ++j ) { - if (is_timeout(temp_time, dht->send_nodes[j].timestamp, PING_TIMEOUT - i)) { - dht->send_nodes[j].timestamp = temp_time; + if (is_timeout(dht->send_nodes[j].timestamp, PING_TIMEOUT - i)) { + dht->send_nodes[j].timestamp = unix_time(); dht->send_nodes[j].ip_port = ip_port; dht->send_nodes[j].id = ping_id; return ping_id; @@ -937,7 +922,6 @@ static int handle_sendnodes_ipv6(void *object, IP_Port source, uint8_t *packet, */ static void get_bunchnodes(DHT *dht, Client_data *list, uint16_t length, uint16_t max_num, uint8_t *client_id) { - uint64_t temp_time = unix_time(); uint32_t i, num = 0; for (i = 0; i < length; ++i) { @@ -946,7 +930,7 @@ static void get_bunchnodes(DHT *dht, Client_data *list, uint16_t length, uint16_ for (a = 0, assoc = &list[i].assoc6; a < 2; a++, assoc = &list[i].assoc4) if (ipport_isset(&(assoc->ip_port)) && - !is_timeout(temp_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { + !is_timeout(assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { getnodes(dht, assoc->ip_port, list[i].client_id, client_id); ++num; @@ -1016,7 +1000,6 @@ int DHT_delfriend(DHT *dht, uint8_t *client_id) int DHT_getfriendip(DHT *dht, uint8_t *client_id, IP_Port *ip_port) { uint32_t i, j; - uint64_t temp_time = unix_time(); ip_reset(&ip_port->ip); ip_port->port = 0; @@ -1032,7 +1015,7 @@ int DHT_getfriendip(DHT *dht, uint8_t *client_id, IP_Port *ip_port) uint32_t a; for (a = 0, assoc = &client->assoc6; a < 2; a++, assoc = &client->assoc4) - if (!is_timeout(temp_time, assoc->timestamp, BAD_NODE_TIMEOUT)) { + if (!is_timeout(assoc->timestamp, BAD_NODE_TIMEOUT)) { *ip_port = assoc->ip_port; return 1; } @@ -1063,14 +1046,14 @@ static void do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, uint8 uint32_t a; for (a = 0, assoc = &client->assoc6; a < 2; a++, assoc = &client->assoc4) - if (!is_timeout(temp_time, assoc->timestamp, KILL_NODE_TIMEOUT)) { - if (is_timeout(temp_time, assoc->last_pinged, PING_INTERVAL)) { + if (!is_timeout(assoc->timestamp, KILL_NODE_TIMEOUT)) { + if (is_timeout(assoc->last_pinged, PING_INTERVAL)) { send_ping_request(dht->ping, assoc->ip_port, client->client_id ); assoc->last_pinged = temp_time; } /* If node is good. */ - if (!is_timeout(temp_time, assoc->timestamp, BAD_NODE_TIMEOUT)) { + if (!is_timeout(assoc->timestamp, BAD_NODE_TIMEOUT)) { client_list[num_nodes] = client; assoc_list[num_nodes] = assoc; ++num_nodes; @@ -1078,8 +1061,7 @@ static void do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, uint8 } } - if ((num_nodes != 0) && - is_timeout(temp_time, *lastgetnode, GET_NODE_INTERVAL)) { + if ((num_nodes != 0) && is_timeout(*lastgetnode, GET_NODE_INTERVAL)) { uint32_t rand_node = rand() % num_nodes; getnodes(dht, assoc_list[rand_node]->ip_port, client_list[rand_node]->client_id, client_id); @@ -1174,9 +1156,6 @@ int route_packet(DHT *dht, uint8_t *client_id, uint8_t *packet, uint32_t length) */ static int friend_iplist(DHT *dht, IP_Port *ip_portlist, uint16_t friend_num) { - int i; - uint64_t temp_time = unix_time(); - if (friend_num >= dht->num_friends) return -1; @@ -1187,20 +1166,21 @@ static int friend_iplist(DHT *dht, IP_Port *ip_portlist, uint16_t friend_num) IP_Port ipv6s[MAX_FRIEND_CLIENTS]; int num_ipv6s = 0; uint8_t connected; + int i; for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { client = &(friend->client_list[i]); connected = 0; /* If ip is not zero and node is good. */ - if (ip_isset(&client->assoc4.ret_ip_port.ip) && !is_timeout(temp_time, client->assoc4.ret_timestamp, BAD_NODE_TIMEOUT)) { + if (ip_isset(&client->assoc4.ret_ip_port.ip) && !is_timeout(client->assoc4.ret_timestamp, BAD_NODE_TIMEOUT)) { ipv4s[num_ipv4s] = client->assoc4.ret_ip_port; ++num_ipv4s; connected = 1; } - if (ip_isset(&client->assoc6.ret_ip_port.ip) && !is_timeout(temp_time, client->assoc6.ret_timestamp, BAD_NODE_TIMEOUT)) { + if (ip_isset(&client->assoc6.ret_ip_port.ip) && !is_timeout(client->assoc6.ret_timestamp, BAD_NODE_TIMEOUT)) { ipv6s[num_ipv6s] = client->assoc6.ret_ip_port; ++num_ipv6s; @@ -1260,7 +1240,6 @@ int route_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint32_t lengt if (ip_num < (MAX_FRIEND_CLIENTS / 2)) return 0; /* Reason for that? */ - uint64_t temp_time = unix_time(); DHT_Friend *friend = &dht->friends_list[num]; Client_data *client; @@ -1283,7 +1262,7 @@ int route_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint32_t lengt /* If ip is not zero and node is good. */ if (ip_isset(&assoc->ret_ip_port.ip) && - !is_timeout(temp_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { + !is_timeout(assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { int retval = sendpacket(dht->c->lossless_udp->net, assoc->ip_port, packet, length); if ((unsigned int)retval == length) { @@ -1313,7 +1292,6 @@ static int routeone_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint IP_Port ip_list[MAX_FRIEND_CLIENTS * 2]; int n = 0; uint32_t i; - uint64_t temp_time = unix_time(); /* extra legwork, because having the outside allocating the space for us * is *usually* good(tm) (bites us in the behind in this case though) */ @@ -1330,7 +1308,7 @@ static int routeone_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint assoc = &client->assoc6; /* If ip is not zero and node is good. */ - if (ip_isset(&assoc->ret_ip_port.ip) && !is_timeout(temp_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { + if (ip_isset(&assoc->ret_ip_port.ip) && !is_timeout(assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { ip_list[n] = assoc->ip_port; ++n; } @@ -1556,6 +1534,9 @@ static void do_NAT(DHT *dht) DHT *new_DHT(Net_Crypto *c) { + /* init time */ + unix_time_update(); + if (c == NULL) return NULL; @@ -1584,6 +1565,8 @@ DHT *new_DHT(Net_Crypto *c) void do_DHT(DHT *dht) { + unix_time_update(); + do_Close(dht); do_DHT_friends(dht); do_NAT(dht); @@ -1860,13 +1843,13 @@ int DHT_load_new(DHT *dht, uint8_t *data, uint32_t length) int DHT_isconnected(DHT *dht) { uint32_t i; - uint64_t temp_time = unix_time(); + unix_time_update(); for (i = 0; i < LCLIENT_LIST; ++i) { Client_data *client = &dht->close_clientlist[i]; - if (!is_timeout(temp_time, client->assoc4.timestamp, BAD_NODE_TIMEOUT) || - !is_timeout(temp_time, client->assoc6.timestamp, BAD_NODE_TIMEOUT)) + if (!is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) || + !is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT)) return 1; } diff --git a/toxcore/LAN_discovery.c b/toxcore/LAN_discovery.c index a4f1ccc2..eb0b95a1 100644 --- a/toxcore/LAN_discovery.c +++ b/toxcore/LAN_discovery.c @@ -26,6 +26,7 @@ #endif #include "LAN_discovery.h" +#include "util.h" #define MAX_INTERFACES 16 @@ -214,7 +215,7 @@ int send_LANdiscovery(uint16_t port, Net_Crypto *c) { uint8_t data[crypto_box_PUBLICKEYBYTES + 1]; data[0] = NET_PACKET_LAN_DISCOVERY; - memcpy(data + 1, c->self_public_key, crypto_box_PUBLICKEYBYTES); + id_copy(data + 1, c->self_public_key); #ifdef __linux send_broadcasts(c->lossless_udp->net, port, data, 1 + crypto_box_PUBLICKEYBYTES); diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 2e8efeac..7710a33c 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -92,7 +92,7 @@ int getfriend_id(Messenger *m, uint8_t *client_id) for (i = 0; i < m->numfriends; ++i) { if (m->friendlist[i].status > 0) - if (memcmp(client_id, m->friendlist[i].client_id, crypto_box_PUBLICKEYBYTES) == 0) + if (id_equal(client_id, m->friendlist[i].client_id)) return i; } @@ -140,7 +140,7 @@ static uint16_t address_checksum(uint8_t *address, uint32_t len) */ void getaddress(Messenger *m, uint8_t *address) { - memcpy(address, m->net_crypto->self_public_key, crypto_box_PUBLICKEYBYTES); + id_copy(address, m->net_crypto->self_public_key); uint32_t nospam = get_nospam(&(m->fr)); memcpy(address + crypto_box_PUBLICKEYBYTES, &nospam, sizeof(nospam)); uint16_t checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum)); @@ -173,7 +173,7 @@ int m_addfriend(Messenger *m, uint8_t *address, uint8_t *data, uint16_t length) return FAERR_TOOLONG; uint8_t client_id[crypto_box_PUBLICKEYBYTES]; - memcpy(client_id, address, crypto_box_PUBLICKEYBYTES); + id_copy(client_id, address); uint16_t check, checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum)); memcpy(&check, address + crypto_box_PUBLICKEYBYTES + sizeof(uint32_t), sizeof(check)); @@ -183,7 +183,7 @@ int m_addfriend(Messenger *m, uint8_t *address, uint8_t *data, uint16_t length) if (length < 1) return FAERR_NOMESSAGE; - if (memcmp(client_id, m->net_crypto->self_public_key, crypto_box_PUBLICKEYBYTES) == 0) + if (id_equal(client_id, m->net_crypto->self_public_key)) return FAERR_OWNKEY; int friend_id = getfriend_id(m, client_id); @@ -214,7 +214,7 @@ int m_addfriend(Messenger *m, uint8_t *address, uint8_t *data, uint16_t length) m->friendlist[i].crypt_connection_id = -1; m->friendlist[i].friendrequest_lastsent = 0; m->friendlist[i].friendrequest_timeout = FRIENDREQUEST_TIMEOUT; - memcpy(m->friendlist[i].client_id, client_id, CLIENT_ID_SIZE); + id_copy(m->friendlist[i].client_id, client_id); m->friendlist[i].statusmessage = calloc(1, 1); m->friendlist[i].statusmessage_length = 1; m->friendlist[i].userstatus = USERSTATUS_NONE; @@ -243,7 +243,7 @@ int m_addfriend_norequest(Messenger *m, uint8_t *client_id) if (realloc_friendlist(m, m->numfriends + 1) != 0) return FAERR_NOMEM; - if (memcmp(client_id, m->net_crypto->self_public_key, crypto_box_PUBLICKEYBYTES) == 0) + if (id_equal(client_id, m->net_crypto->self_public_key)) return FAERR_OWNKEY; memset(&(m->friendlist[m->numfriends]), 0, sizeof(Friend)); @@ -256,7 +256,7 @@ int m_addfriend_norequest(Messenger *m, uint8_t *client_id) m->friendlist[i].status = FRIEND_CONFIRMED; m->friendlist[i].crypt_connection_id = -1; m->friendlist[i].friendrequest_lastsent = 0; - memcpy(m->friendlist[i].client_id, client_id, CLIENT_ID_SIZE); + id_copy(m->friendlist[i].client_id, client_id); m->friendlist[i].statusmessage = calloc(1, 1); m->friendlist[i].statusmessage_length = 1; m->friendlist[i].userstatus = USERSTATUS_NONE; @@ -728,7 +728,7 @@ static int group_num(Messenger *m, uint8_t *group_public_key) uint32_t i; for (i = 0; i < m->numchats; ++i) { - if (memcmp(m->chats[i]->self_public_key, group_public_key, crypto_box_PUBLICKEYBYTES) == 0) + if (id_equal(m->chats[i]->self_public_key, group_public_key)) return i; } @@ -917,8 +917,8 @@ int join_groupchat(Messenger *m, int friendnumber, uint8_t *friend_group_public_ if (groupnum == -1) return -1; - memcpy(data, friend_group_public_key, crypto_box_PUBLICKEYBYTES); - memcpy(data + crypto_box_PUBLICKEYBYTES, m->chats[groupnum]->self_public_key, crypto_box_PUBLICKEYBYTES); + id_copy(data, friend_group_public_key); + id_copy(data + crypto_box_PUBLICKEYBYTES, m->chats[groupnum]->self_public_key); if (write_cryptpacket_id(m, friendnumber, PACKET_ID_JOIN_GROUPCHAT, data, sizeof(data))) { chat_bootstrap_nonlazy(m->chats[groupnum], get_friend_ipport(m, friendnumber), @@ -965,7 +965,7 @@ static int handle_group(void *object, IP_Port source, uint8_t *packet, uint32_t if (m->chats[i] == NULL) continue; - if (memcmp(packet + 1, m->chats[i]->self_public_key, crypto_box_PUBLICKEYBYTES) == 0) + if (id_equal(packet + 1, m->chats[i]->self_public_key)) return handle_groupchatpacket(m->chats[i], source, packet, length); } @@ -1769,6 +1769,8 @@ static char *ID2String(uint8_t *client_id) /* The main loop that needs to be run at least 20 times per second. */ void doMessenger(Messenger *m) { + unix_time_update(); + networking_poll(m->net); do_DHT(m->dht); @@ -1996,7 +1998,7 @@ static int Messenger_load_old(Messenger *m, uint8_t *data, uint32_t length) } else if (friend_list[i].status != 0) { /* TODO: This is not a good way to do this. */ uint8_t address[FRIEND_ADDRESS_SIZE]; - memcpy(address, friend_list[i].client_id, crypto_box_PUBLICKEYBYTES); + id_copy(address, friend_list[i].client_id); memcpy(address + crypto_box_PUBLICKEYBYTES, &(friend_list[i].friendrequest_nospam), sizeof(uint32_t)); uint16_t checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum)); memcpy(address + crypto_box_PUBLICKEYBYTES + sizeof(uint32_t), &checksum, sizeof(checksum)); @@ -2130,7 +2132,7 @@ static int messenger_load_state_callback(void *outer, uint8_t *data, uint32_t le } else if (friends[i].status != 0) { /* TODO: This is not a good way to do this. */ uint8_t address[FRIEND_ADDRESS_SIZE]; - memcpy(address, friends[i].client_id, crypto_box_PUBLICKEYBYTES); + id_copy(address, friends[i].client_id); memcpy(address + crypto_box_PUBLICKEYBYTES, &(friends[i].friendrequest_nospam), sizeof(uint32_t)); uint16_t checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum)); memcpy(address + crypto_box_PUBLICKEYBYTES + sizeof(uint32_t), &checksum, sizeof(checksum)); diff --git a/toxcore/friend_requests.c b/toxcore/friend_requests.c index c821d998..67977c23 100644 --- a/toxcore/friend_requests.c +++ b/toxcore/friend_requests.c @@ -26,6 +26,7 @@ #endif #include "friend_requests.h" +#include "util.h" /* Try to send a friend request to peer with public_key. * data is the data in the request and length is the length. @@ -102,7 +103,7 @@ static void addto_receivedlist(Friend_Requests *fr, uint8_t *client_id) if (fr->received_requests_index >= MAX_RECEIVED_STORED) fr->received_requests_index = 0; - memcpy(fr->received_requests[fr->received_requests_index], client_id, crypto_box_PUBLICKEYBYTES); + id_copy(fr->received_requests[fr->received_requests_index], client_id); ++fr->received_requests_index; } @@ -115,10 +116,9 @@ static int request_received(Friend_Requests *fr, uint8_t *client_id) { uint32_t i; - for (i = 0; i < MAX_RECEIVED_STORED; ++i) { - if (memcmp(fr->received_requests[i], client_id, crypto_box_PUBLICKEYBYTES) == 0) + for (i = 0; i < MAX_RECEIVED_STORED; ++i) + if (id_equal(fr->received_requests[i], client_id)) return 1; - } return 0; } diff --git a/toxcore/group_chats.c b/toxcore/group_chats.c index 0d6d6972..8609e45b 100644 --- a/toxcore/group_chats.c +++ b/toxcore/group_chats.c @@ -27,7 +27,7 @@ #endif #include "group_chats.h" - +#include "util.h" #define GROUPCHAT_MAXDATA_LENGTH (MAX_DATA_SIZE - (1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES)) #define GROUPCHAT_MAXPLAINDATA_LENGTH (GROUPCHAT_MAXDATA_LENGTH - crypto_box_MACBYTES) @@ -67,16 +67,14 @@ static int peer_in_chat(Group_Chat *chat, uint8_t *client_id) { uint32_t i; - for (i = 0; i < chat->numpeers; ++i) { - /* Equal */ - if (memcmp(chat->group[i].client_id, client_id, crypto_box_PUBLICKEYBYTES) == 0) + for (i = 0; i < chat->numpeers; ++i) + if (id_equal(chat->group[i].client_id, client_id)) return i; - } return -1; } -#define BAD_NODE_TIMEOUT 30 +#define BAD_GROUPNODE_TIMEOUT 30 /* * Check if peer is closer to us that the other peers in the list and if the peer is in the list. @@ -87,19 +85,18 @@ static int peer_in_chat(Group_Chat *chat, uint8_t *client_id) static int peer_okping(Group_Chat *chat, uint8_t *client_id) { uint32_t i, j = 0; - uint64_t temp_time = unix_time(); - if (memcmp(chat->self_public_key, client_id, crypto_box_PUBLICKEYBYTES) == 0) + if (id_equal(chat->self_public_key, client_id)) return -1; for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { - if (chat->close[i].last_recv + BAD_NODE_TIMEOUT < temp_time) { + if (is_timeout(chat->close[i].last_recv, BAD_GROUPNODE_TIMEOUT)) { ++j; continue; } /* Equal */ - if (memcmp(chat->close[i].client_id, client_id, crypto_box_PUBLICKEYBYTES) == 0) + if (id_equal(chat->close[i].client_id, client_id)) return -1; if (id_closest(chat->self_public_key, chat->close[i].client_id, client_id) == 2) @@ -121,29 +118,28 @@ static int peer_okping(Group_Chat *chat, uint8_t *client_id) static int add_closepeer(Group_Chat *chat, uint8_t *client_id, IP_Port ip_port) { uint32_t i; - uint64_t temp_time = unix_time(); for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { /* Check if node is already in list, if it is update its last_recv */ - if (memcmp(chat->close[i].client_id, client_id, crypto_box_PUBLICKEYBYTES) == 0) { - chat->close[i].last_recv = temp_time; + if (id_equal(chat->close[i].client_id, client_id)) { + chat->close[i].last_recv = unix_time(); return 0; } } for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { /* Try replacing bad nodes first */ - if (chat->close[i].last_recv + BAD_NODE_TIMEOUT < temp_time) { - memcpy(chat->close[i].client_id, client_id, crypto_box_PUBLICKEYBYTES); + if (is_timeout(chat->close[i].last_recv, BAD_GROUPNODE_TIMEOUT)) { + id_copy(chat->close[i].client_id, client_id); chat->close[i].ip_port = ip_port; - chat->close[i].last_recv = temp_time; + chat->close[i].last_recv = unix_time(); return 0; } } for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { /* Replace nodes if given one is closer. */ if (id_closest(chat->self_public_key, chat->close[i].client_id, client_id) == 2) { - memcpy(chat->close[i].client_id, client_id, crypto_box_PUBLICKEYBYTES); + id_copy(chat->close[i].client_id, client_id); chat->close[i].ip_port = ip_port; - chat->close[i].last_recv = temp_time; + chat->close[i].last_recv = unix_time(); return 0; } } @@ -154,7 +150,7 @@ static int add_closepeer(Group_Chat *chat, uint8_t *client_id, IP_Port ip_port) static int send_groupchatpacket(Group_Chat *chat, IP_Port ip_port, uint8_t *public_key, uint8_t *data, uint32_t length, uint8_t request_id) { - if (memcmp(chat->self_public_key, public_key, crypto_box_PUBLICKEYBYTES) == 0) + if (id_equal(chat->self_public_key, public_key)) return -1; uint8_t packet[MAX_DATA_SIZE]; @@ -180,11 +176,12 @@ static uint8_t sendto_allpeers(Group_Chat *chat, uint8_t *data, uint16_t length, { uint16_t sent = 0; uint32_t i; - uint64_t temp_time = unix_time(); for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { - if (ip_isset(&chat->close[i].ip_port.ip) && chat->close[i].last_recv + BAD_NODE_TIMEOUT > temp_time) { - if (send_groupchatpacket(chat, chat->close[i].ip_port, chat->close[i].client_id, data, length, request_id) == 0) + if (ip_isset(&chat->close[i].ip_port.ip) && + !is_timeout(chat->close[i].last_recv, BAD_GROUPNODE_TIMEOUT)) { + if (send_groupchatpacket(chat, chat->close[i].ip_port, chat->close[i].client_id, + data, length, request_id) == 0) ++sent; } } @@ -214,7 +211,7 @@ static int addpeer(Group_Chat *chat, uint8_t *client_id) return -1; chat->group = temp; - memcpy(chat->group[chat->numpeers].client_id, client_id, crypto_box_PUBLICKEYBYTES); + id_copy(chat->group[chat->numpeers].client_id, client_id); ++chat->numpeers; return (chat->numpeers - 1); } @@ -232,14 +229,11 @@ static int delpeer(Group_Chat *chat, uint8_t *client_id) for (i = 0; i < chat->numpeers; ++i) { /* Equal */ - if (memcmp(chat->group[i].client_id, client_id, crypto_box_PUBLICKEYBYTES) == 0) { + if (id_equal(chat->group[i].client_id, client_id)) { --chat->numpeers; - if (chat->numpeers != i) { - memcpy( chat->group[i].client_id, - chat->group[chat->numpeers].client_id, - crypto_box_PUBLICKEYBYTES ); - } + if (chat->numpeers != i) + id_copy(chat->group[i].client_id, chat->group[chat->numpeers].client_id); temp = realloc(chat->group, sizeof(Group_Peer) * (chat->numpeers)); @@ -276,22 +270,23 @@ int group_peername(Group_Chat *chat, int peernum, uint8_t *name) /* min time between pings sent to one peer in seconds */ +/* TODO: move this to global section */ #define PING_TIMEOUT 5 + static int send_getnodes(Group_Chat *chat, IP_Port ip_port, int peernum) { if ((uint32_t)peernum >= chat->numpeers) return -1; - uint64_t temp_time = unix_time(); - - getnodes_data contents; - - if (chat->group[peernum].last_pinged + PING_TIMEOUT > temp_time) + if (!is_timeout(chat->group[peernum].last_pinged, PING_TIMEOUT)) return -1; + getnodes_data contents; contents.pingid = ((uint64_t)random_int() << 32) + random_int(); - chat->group[peernum].last_pinged = temp_time; + + chat->group[peernum].last_pinged = unix_time(); chat->group[peernum].pingid = contents.pingid; + return send_groupchatpacket(chat, ip_port, chat->group[peernum].client_id, (uint8_t *)&contents, sizeof(contents), 48); } @@ -303,11 +298,10 @@ static int send_sendnodes(Group_Chat *chat, IP_Port ip_port, int peernum, uint64 sendnodes_data contents; contents.pingid = pingid; uint32_t i, j = 0; - uint64_t temp_time = unix_time(); for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { - if (chat->close[i].last_recv + BAD_NODE_TIMEOUT > temp_time) { - memcpy(contents.nodes[j].client_id, chat->close[i].client_id, crypto_box_PUBLICKEYBYTES); + if (!is_timeout(chat->close[i].last_recv, BAD_GROUPNODE_TIMEOUT)) { + id_copy(contents.nodes[j].client_id, chat->close[i].client_id); contents.nodes[j].ip_port = chat->close[i].ip_port; ++j; } @@ -346,7 +340,7 @@ static int handle_sendnodes(Group_Chat *chat, IP_Port source, int peernum, uint8 if ((len - sizeof(uint64_t)) % sizeof(groupchat_nodes) != 0) return 1; - if (chat->group[peernum].last_pinged + PING_TIMEOUT < unix_time()) + if (is_timeout(chat->group[peernum].last_pinged, PING_TIMEOUT)) return 1; sendnodes_data contents; @@ -376,7 +370,9 @@ static int handle_sendnodes(Group_Chat *chat, IP_Port source, int peernum, uint8 add_closepeer(chat, chat->group[peernum].client_id, source); return 0; } + #define GROUP_DATA_MIN_SIZE (crypto_box_PUBLICKEYBYTES + sizeof(uint32_t) + 1) + static int handle_data(Group_Chat *chat, uint8_t *data, uint32_t len) { if (len < GROUP_DATA_MIN_SIZE) @@ -392,7 +388,6 @@ static int handle_data(Group_Chat *chat, uint8_t *data, uint32_t len) if (peernum == -1) return 1; - uint64_t temp_time = unix_time(); /* Spam prevention (1 message per peer per second limit.) if (chat->group[peernum].last_recv == temp_time) @@ -421,7 +416,8 @@ static int handle_data(Group_Chat *chat, uint8_t *data, uint32_t len) if (contents_len != 0) return 1; - chat->group[peernum].last_recv_msgping = temp_time; + chat->group[peernum].last_recv_msgping = unix_time(); + break; case 16: /* If message is new peer */ if (contents_len != crypto_box_PUBLICKEYBYTES) @@ -463,7 +459,7 @@ static uint8_t send_data(Group_Chat *chat, uint8_t *data, uint32_t len, uint8_t uint32_t message_num = htonl(chat->message_number); //TODO - memcpy(packet, chat->self_public_key, crypto_box_PUBLICKEYBYTES); + id_copy(packet, chat->self_public_key); memcpy(packet + crypto_box_PUBLICKEYBYTES, &message_num, sizeof(message_num)); memcpy(packet + GROUP_DATA_MIN_SIZE, data, len); packet[crypto_box_PUBLICKEYBYTES + sizeof(message_num)] = message_id; @@ -489,7 +485,7 @@ int handle_groupchatpacket(Group_Chat *chat, IP_Port source, uint8_t *packet, ui if (len <= 0) return 1; - if (memcmp(chat->self_public_key, public_key, crypto_box_PUBLICKEYBYTES) == 0) + if (id_equal(chat->self_public_key, public_key)) return 1; int peernum = peer_in_chat(chat, public_key); @@ -548,16 +544,16 @@ Group_Chat *new_groupchat(Networking_Core *net) static void ping_close(Group_Chat *chat) { uint32_t i; - uint64_t temp_time = unix_time(); for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { - if (chat->close[i].last_recv < temp_time + BAD_NODE_TIMEOUT) { + /* previous condition was always true, assuming this is the wanted one: */ + if (!is_timeout(chat->close[i].last_recv, BAD_GROUPNODE_TIMEOUT)) { int peernum = peer_in_chat(chat, chat->close[i].client_id); if (peernum == -1) continue; - if (chat->group[peernum].last_pinged + NODE_PING_INTERVAL < temp_time) + if (is_timeout(chat->group[peernum].last_pinged, NODE_PING_INTERVAL)) send_getnodes(chat, chat->close[i].ip_port, peernum); } } @@ -584,4 +580,3 @@ void chat_bootstrap_nonlazy(Group_Chat *chat, IP_Port ip_port, uint8_t *client_i send_getnodes(chat, ip_port, addpeer(chat, client_id)); add_closepeer(chat, client_id, ip_port); } - diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index b7e3ced7..0a7ff665 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -29,6 +29,7 @@ #endif #include "net_crypto.h" +#include "util.h" #define CONN_NO_CONNECTION 0 #define CONN_HANDSHAKE_SENT 1 @@ -268,8 +269,8 @@ int create_request(uint8_t *send_public_key, uint8_t *send_secret_key, uint8_t * return -1; packet[0] = NET_PACKET_CRYPTO; - memcpy(packet + 1, recv_public_key, crypto_box_PUBLICKEYBYTES); - memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, send_public_key, crypto_box_PUBLICKEYBYTES); + id_copy(packet + 1, recv_public_key); + id_copy(packet + 1 + crypto_box_PUBLICKEYBYTES, send_public_key); memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES * 2, nonce, crypto_box_NONCEBYTES); return len + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES; @@ -286,8 +287,8 @@ int handle_request(uint8_t *self_public_key, uint8_t *self_secret_key, uint8_t * { if (length > crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING && length <= MAX_DATA_SIZE) { - if (memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) { - memcpy(public_key, packet + 1 + crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); + if (id_equal(packet + 1, self_public_key)) { + id_copy(public_key, packet + 1 + crypto_box_PUBLICKEYBYTES); uint8_t nonce[crypto_box_NONCEBYTES]; uint8_t temp[MAX_DATA_SIZE]; memcpy(nonce, packet + 1 + crypto_box_PUBLICKEYBYTES * 2, crypto_box_NONCEBYTES); @@ -323,7 +324,7 @@ static int cryptopacket_handle(void *object, IP_Port source, uint8_t *packet, ui length > MAX_DATA_SIZE + ENCRYPTION_PADDING) return 1; - if (memcmp(packet + 1, dht->c->self_public_key, crypto_box_PUBLICKEYBYTES) == 0) { // Check if request is for us. + if (id_equal(packet + 1, dht->c->self_public_key)) { // Check if request is for us. uint8_t public_key[crypto_box_PUBLICKEYBYTES]; uint8_t data[MAX_DATA_SIZE]; uint8_t number; @@ -361,7 +362,7 @@ static int send_cryptohandshake(Net_Crypto *c, int connection_id, uint8_t *publi new_nonce(nonce); memcpy(temp, secret_nonce, crypto_box_NONCEBYTES); - memcpy(temp + crypto_box_NONCEBYTES, session_key, crypto_box_PUBLICKEYBYTES); + id_copy(temp + crypto_box_NONCEBYTES, session_key); int len = encrypt_data(public_key, c->self_secret_key, nonce, temp, crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + temp_data); @@ -370,7 +371,7 @@ static int send_cryptohandshake(Net_Crypto *c, int connection_id, uint8_t *publi return 0; temp_data[0] = 2; - memcpy(temp_data + 1, c->self_public_key, crypto_box_PUBLICKEYBYTES); + id_copy(temp_data + 1, c->self_public_key); memcpy(temp_data + 1 + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES); return write_packet(c->lossless_udp, connection_id, temp_data, len + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES); @@ -396,7 +397,7 @@ static int handle_cryptohandshake(Net_Crypto *c, uint8_t *public_key, uint8_t *s uint8_t temp[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES]; - memcpy(public_key, data + 1, crypto_box_PUBLICKEYBYTES); + id_copy(public_key, data + 1); int len = decrypt_data(public_key, c->self_secret_key, data + 1 + crypto_box_PUBLICKEYBYTES, data + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, @@ -406,7 +407,7 @@ static int handle_cryptohandshake(Net_Crypto *c, uint8_t *public_key, uint8_t *s return 0; memcpy(secret_nonce, temp, crypto_box_NONCEBYTES); - memcpy(session_key, temp + crypto_box_NONCEBYTES, crypto_box_PUBLICKEYBYTES); + id_copy(session_key, temp + crypto_box_NONCEBYTES); return 1; } @@ -419,11 +420,10 @@ static int getcryptconnection_id(Net_Crypto *c, uint8_t *public_key) { uint32_t i; - for (i = 0; i < c->crypto_connections_length; ++i) { + for (i = 0; i < c->crypto_connections_length; ++i) if (c->crypto_connections[i].status != CONN_NO_CONNECTION) - if (memcmp(public_key, c->crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) + if (id_equal(public_key, c->crypto_connections[i].public_key)) return i; - } return -1; } @@ -483,7 +483,7 @@ int crypto_connect(Net_Crypto *c, uint8_t *public_key, IP_Port ip_port) c->crypto_connections[i].number = id_new; c->crypto_connections[i].status = CONN_HANDSHAKE_SENT; random_nonce(c->crypto_connections[i].recv_nonce); - memcpy(c->crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES); + id_copy(c->crypto_connections[i].public_key, public_key); crypto_box_keypair(c->crypto_connections[i].sessionpublic_key, c->crypto_connections[i].sessionsecret_key); c->crypto_connections[i].timeout = unix_time() + CRYPTO_HANDSHAKE_TIMEOUT; @@ -604,9 +604,9 @@ int accept_crypto_inbound(Net_Crypto *c, int connection_id, uint8_t *public_key, c->crypto_connections[i].timeout = unix_time() + CRYPTO_HANDSHAKE_TIMEOUT; random_nonce(c->crypto_connections[i].recv_nonce); memcpy(c->crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES); - memcpy(c->crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES); + id_copy(c->crypto_connections[i].peersessionpublic_key, session_key); increment_nonce(c->crypto_connections[i].sent_nonce); - memcpy(c->crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES); + id_copy(c->crypto_connections[i].public_key, public_key); crypto_box_keypair(c->crypto_connections[i].sessionpublic_key, c->crypto_connections[i].sessionsecret_key); @@ -658,7 +658,7 @@ void new_keys(Net_Crypto *c) */ void save_keys(Net_Crypto *c, uint8_t *keys) { - memcpy(keys, c->self_public_key, crypto_box_PUBLICKEYBYTES); + id_copy(keys, c->self_public_key); memcpy(keys + crypto_box_PUBLICKEYBYTES, c->self_secret_key, crypto_box_SECRETKEYBYTES); } @@ -667,7 +667,7 @@ void save_keys(Net_Crypto *c, uint8_t *keys) */ void load_keys(Net_Crypto *c, uint8_t *keys) { - memcpy(c->self_public_key, keys, crypto_box_PUBLICKEYBYTES); + id_copy(c->self_public_key, keys); memcpy(c->self_secret_key, keys + crypto_box_PUBLICKEYBYTES, crypto_box_SECRETKEYBYTES); } @@ -692,9 +692,9 @@ static void receive_crypto(Net_Crypto *c) len = read_packet(c->lossless_udp, c->crypto_connections[i].number, temp_data); if (handle_cryptohandshake(c, public_key, secret_nonce, session_key, temp_data, len)) { - if (memcmp(public_key, c->crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) { + if (id_equal(public_key, c->crypto_connections[i].public_key)) { memcpy(c->crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES); - memcpy(c->crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES); + id_copy(c->crypto_connections[i].peersessionpublic_key, session_key); increment_nonce(c->crypto_connections[i].sent_nonce); uint32_t zero = 0; encrypt_precompute(c->crypto_connections[i].peersessionpublic_key, diff --git a/toxcore/network.h b/toxcore/network.h index 1253c07e..11d6be67 100644 --- a/toxcore/network.h +++ b/toxcore/network.h @@ -97,9 +97,6 @@ typedef int sock_t; #define TOX_PORTRANGE_TO 33455 #define TOX_PORT_DEFAULT TOX_PORTRANGE_FROM -/* Current time, unix format */ -#define unix_time() ((uint64_t)time(NULL)) - typedef union { uint8_t uint8[4]; uint16_t uint16[2]; diff --git a/toxcore/ping.c b/toxcore/ping.c index b9940ce1..e4bc16d9 100644 --- a/toxcore/ping.c +++ b/toxcore/ping.c @@ -40,7 +40,7 @@ typedef struct { static bool is_ping_timeout(uint64_t time) { - return (time + PING_TIMEOUT) < now(); + return is_timeout(time, PING_TIMEOUT); } static void remove_timeouts(PING *ping) // O(n) @@ -83,7 +83,7 @@ static uint64_t add_ping(PING *ping, IP_Port ipp) // O(n) p = (ping->pos_pings + ping->num_pings) % PING_NUM_MAX; ping->pings[p].ip_port = ipp; - ping->pings[p].timestamp = now(); + ping->pings[p].timestamp = unix_time(); ping->pings[p].id = random_64b(); ping->num_pings++; @@ -122,14 +122,14 @@ int send_ping_request(PING *ping, IP_Port ipp, uint8_t *client_id) int rc; uint64_t ping_id; - if (is_pinging(ping, ipp, 0) || id_eq(client_id, ping->c->self_public_key)) + if (is_pinging(ping, ipp, 0) || id_equal(client_id, ping->c->self_public_key)) return 1; // Generate random ping_id. ping_id = add_ping(ping, ipp); pk[0] = NET_PACKET_PING_REQUEST; - id_cpy(pk + 1, ping->c->self_public_key); // Our pubkey + id_copy(pk + 1, ping->c->self_public_key); // Our pubkey new_nonce(pk + 1 + CLIENT_ID_SIZE); // Generate new nonce // Encrypt ping_id using recipient privkey @@ -150,11 +150,11 @@ static int send_ping_response(PING *ping, IP_Port ipp, uint8_t *client_id, uint6 uint8_t pk[DHT_PING_SIZE]; int rc; - if (id_eq(client_id, ping->c->self_public_key)) + if (id_equal(client_id, ping->c->self_public_key)) return 1; pk[0] = NET_PACKET_PING_RESPONSE; - id_cpy(pk + 1, ping->c->self_public_key); // Our pubkey + id_copy(pk + 1, ping->c->self_public_key); // Our pubkey new_nonce(pk + 1 + CLIENT_ID_SIZE); // Generate new nonce // Encrypt ping_id using recipient privkey @@ -181,7 +181,7 @@ static int handle_ping_request(void *_dht, IP_Port source, uint8_t *packet, uint PING *ping = dht->ping; - if (id_eq(packet + 1, ping->c->self_public_key)) + if (id_equal(packet + 1, ping->c->self_public_key)) return 1; // Decrypt ping_id @@ -213,7 +213,7 @@ static int handle_ping_response(void *_dht, IP_Port source, uint8_t *packet, uin PING *ping = dht->ping; - if (id_eq(packet + 1, ping->c->self_public_key)) + if (id_equal(packet + 1, ping->c->self_public_key)) return 1; // Decrypt ping_id @@ -277,19 +277,12 @@ int add_toping(PING *ping, uint8_t *client_id, IP_Port ip_port) /* Ping all the valid nodes in the toping list every TIME_TOPING seconds. * This function must be run at least once every TIME_TOPING seconds. */ -static int is_timeout(uint64_t time_now, uint64_t timestamp, uint64_t timeout) -{ - return timestamp + timeout <= time_now; -} - void do_toping(PING *ping) { - uint64_t temp_time = unix_time(); - - if (!is_timeout(temp_time, ping->last_toping, TIME_TOPING)) + if (!is_timeout(ping->last_toping, TIME_TOPING)) return; - ping->last_toping = temp_time; + ping->last_toping = unix_time(); uint32_t i; for (i = 0; i < MAX_TOPING; ++i) { diff --git a/toxcore/util.c b/toxcore/util.c index a1de6392..3fdac9dd 100644 --- a/toxcore/util.c +++ b/toxcore/util.c @@ -16,11 +16,6 @@ #include "util.h" -uint64_t now() -{ - return time(NULL); -} - uint64_t random_64b() { uint64_t r; @@ -33,16 +28,39 @@ uint64_t random_64b() return r; } -bool id_eq(uint8_t *dest, uint8_t *src) +/* don't call into system billions of times for no reason */ +static uint64_t unix_time_value; + +void unix_time_update() +{ + unix_time_value = (uint64_t)time(NULL); +} + +uint64_t unix_time() +{ + return unix_time_value; +} + +int is_timeout(uint64_t timestamp, uint64_t timeout) +{ + return timestamp + timeout <= unix_time_value; +} + + +/* id functions */ +bool id_equal(uint8_t *dest, uint8_t *src) { return memcmp(dest, src, CLIENT_ID_SIZE) == 0; } -void id_cpy(uint8_t *dest, uint8_t *src) +uint32_t id_copy(uint8_t *dest, uint8_t *src) { memcpy(dest, src, CLIENT_ID_SIZE); + return CLIENT_ID_SIZE; } + +/* state load/save */ int load_state(load_state_callback_func load_state_callback, void *outer, uint8_t *data, uint32_t length, uint16_t cookie_inner) { diff --git a/toxcore/util.h b/toxcore/util.h index 13ab4792..3ecefd9c 100644 --- a/toxcore/util.h +++ b/toxcore/util.h @@ -11,11 +11,19 @@ #include #include -uint64_t now(); uint64_t random_64b(); -bool id_eq(uint8_t *dest, uint8_t *src); -void id_cpy(uint8_t *dest, uint8_t *src); +void unix_time_update(); +uint64_t unix_time(); +int is_timeout(uint64_t timestamp, uint64_t timeout); + + +/* id functions */ +bool id_equal(uint8_t *dest, uint8_t *src); +uint32_t id_copy(uint8_t *dest, uint8_t *src); /* return value is CLIENT_ID_SIZE */ + + +/* state load/save */ typedef int (*load_state_callback_func)(void *outer, uint8_t *data, uint32_t len, uint16_t type); int load_state(load_state_callback_func load_state_callback, void *outer, uint8_t *data, uint32_t length, uint16_t cookie_inner); -- cgit v1.2.3 From b891446c31c5319182fcf98dd6e1edffef5857d6 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 25 Oct 2013 14:43:47 -0400 Subject: For security reasons, keep memcpy's and memcmp's in crypto functions. --- toxcore/net_crypto.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 7ae7c502..a9aa77f9 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -29,7 +29,6 @@ #endif #include "net_crypto.h" -#include "util.h" static uint8_t crypt_connection_id_not_valid(Net_Crypto *c, int crypt_connection_id) { @@ -263,8 +262,8 @@ int create_request(uint8_t *send_public_key, uint8_t *send_secret_key, uint8_t * return -1; packet[0] = NET_PACKET_CRYPTO; - id_copy(packet + 1, recv_public_key); - id_copy(packet + 1 + crypto_box_PUBLICKEYBYTES, send_public_key); + memcpy(packet + 1, recv_public_key, crypto_box_PUBLICKEYBYTES); + memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, send_public_key, crypto_box_PUBLICKEYBYTES); memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES * 2, nonce, crypto_box_NONCEBYTES); return len + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES; @@ -281,8 +280,8 @@ int handle_request(uint8_t *self_public_key, uint8_t *self_secret_key, uint8_t * { if (length > crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING && length <= MAX_DATA_SIZE) { - if (id_equal(packet + 1, self_public_key)) { - id_copy(public_key, packet + 1 + crypto_box_PUBLICKEYBYTES); + if (memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) { + memcpy(public_key, packet + 1 + crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); uint8_t nonce[crypto_box_NONCEBYTES]; uint8_t temp[MAX_DATA_SIZE]; memcpy(nonce, packet + 1 + crypto_box_PUBLICKEYBYTES * 2, crypto_box_NONCEBYTES); @@ -318,7 +317,7 @@ static int cryptopacket_handle(void *object, IP_Port source, uint8_t *packet, ui length > MAX_DATA_SIZE + ENCRYPTION_PADDING) return 1; - if (id_equal(packet + 1, dht->c->self_public_key)) { // Check if request is for us. + if (memcmp(packet + 1, dht->c->self_public_key, crypto_box_PUBLICKEYBYTES) == 0) { // Check if request is for us. uint8_t public_key[crypto_box_PUBLICKEYBYTES]; uint8_t data[MAX_DATA_SIZE]; uint8_t number; @@ -356,7 +355,7 @@ static int send_cryptohandshake(Net_Crypto *c, int connection_id, uint8_t *publi new_nonce(nonce); memcpy(temp, secret_nonce, crypto_box_NONCEBYTES); - id_copy(temp + crypto_box_NONCEBYTES, session_key); + memcpy(temp + crypto_box_NONCEBYTES, session_key, crypto_box_PUBLICKEYBYTES); int len = encrypt_data(public_key, c->self_secret_key, nonce, temp, crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + temp_data); @@ -365,7 +364,7 @@ static int send_cryptohandshake(Net_Crypto *c, int connection_id, uint8_t *publi return 0; temp_data[0] = 2; - id_copy(temp_data + 1, c->self_public_key); + memcpy(temp_data + 1, c->self_public_key, crypto_box_PUBLICKEYBYTES); memcpy(temp_data + 1 + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES); return write_packet(c->lossless_udp, connection_id, temp_data, len + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES); @@ -391,7 +390,7 @@ static int handle_cryptohandshake(Net_Crypto *c, uint8_t *public_key, uint8_t *s uint8_t temp[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES]; - id_copy(public_key, data + 1); + memcpy(public_key, data + 1, crypto_box_PUBLICKEYBYTES); int len = decrypt_data(public_key, c->self_secret_key, data + 1 + crypto_box_PUBLICKEYBYTES, data + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, @@ -401,7 +400,7 @@ static int handle_cryptohandshake(Net_Crypto *c, uint8_t *public_key, uint8_t *s return 0; memcpy(secret_nonce, temp, crypto_box_NONCEBYTES); - id_copy(session_key, temp + crypto_box_NONCEBYTES); + memcpy(session_key, temp + crypto_box_NONCEBYTES, crypto_box_PUBLICKEYBYTES); return 1; } @@ -414,10 +413,11 @@ static int getcryptconnection_id(Net_Crypto *c, uint8_t *public_key) { uint32_t i; - for (i = 0; i < c->crypto_connections_length; ++i) + for (i = 0; i < c->crypto_connections_length; ++i) { if (c->crypto_connections[i].status != CRYPTO_CONN_NO_CONNECTION) - if (id_equal(public_key, c->crypto_connections[i].public_key)) + if (memcmp(public_key, c->crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) return i; + } return -1; } @@ -477,7 +477,7 @@ int crypto_connect(Net_Crypto *c, uint8_t *public_key, IP_Port ip_port) c->crypto_connections[i].number = id_new; c->crypto_connections[i].status = CRYPTO_CONN_HANDSHAKE_SENT; random_nonce(c->crypto_connections[i].recv_nonce); - id_copy(c->crypto_connections[i].public_key, public_key); + memcpy(c->crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES); crypto_box_keypair(c->crypto_connections[i].sessionpublic_key, c->crypto_connections[i].sessionsecret_key); c->crypto_connections[i].timeout = unix_time() + CRYPTO_HANDSHAKE_TIMEOUT; @@ -598,9 +598,9 @@ int accept_crypto_inbound(Net_Crypto *c, int connection_id, uint8_t *public_key, c->crypto_connections[i].timeout = unix_time() + CRYPTO_HANDSHAKE_TIMEOUT; random_nonce(c->crypto_connections[i].recv_nonce); memcpy(c->crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES); - id_copy(c->crypto_connections[i].peersessionpublic_key, session_key); + memcpy(c->crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES); increment_nonce(c->crypto_connections[i].sent_nonce); - id_copy(c->crypto_connections[i].public_key, public_key); + memcpy(c->crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES); crypto_box_keypair(c->crypto_connections[i].sessionpublic_key, c->crypto_connections[i].sessionsecret_key); @@ -652,7 +652,7 @@ void new_keys(Net_Crypto *c) */ void save_keys(Net_Crypto *c, uint8_t *keys) { - id_copy(keys, c->self_public_key); + memcpy(keys, c->self_public_key, crypto_box_PUBLICKEYBYTES); memcpy(keys + crypto_box_PUBLICKEYBYTES, c->self_secret_key, crypto_box_SECRETKEYBYTES); } @@ -661,7 +661,7 @@ void save_keys(Net_Crypto *c, uint8_t *keys) */ void load_keys(Net_Crypto *c, uint8_t *keys) { - id_copy(c->self_public_key, keys); + memcpy(c->self_public_key, keys, crypto_box_PUBLICKEYBYTES); memcpy(c->self_secret_key, keys + crypto_box_PUBLICKEYBYTES, crypto_box_SECRETKEYBYTES); } @@ -686,9 +686,9 @@ static void receive_crypto(Net_Crypto *c) len = read_packet(c->lossless_udp, c->crypto_connections[i].number, temp_data); if (handle_cryptohandshake(c, public_key, secret_nonce, session_key, temp_data, len)) { - if (id_equal(public_key, c->crypto_connections[i].public_key)) { + if (memcmp(public_key, c->crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) { memcpy(c->crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES); - id_copy(c->crypto_connections[i].peersessionpublic_key, session_key); + memcpy(c->crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES); increment_nonce(c->crypto_connections[i].sent_nonce); uint32_t zero = 0; encrypt_precompute(c->crypto_connections[i].peersessionpublic_key, -- cgit v1.2.3 From 9ccdac0e8268776c2cd7f9f6af347d44ca03c73d Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 25 Oct 2013 14:47:34 -0400 Subject: All modules using unix_time should run unix_time_update() --- toxcore/group_chats.c | 3 +++ toxcore/net_crypto.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/toxcore/group_chats.c b/toxcore/group_chats.c index 8609e45b..fdf6e834 100644 --- a/toxcore/group_chats.c +++ b/toxcore/group_chats.c @@ -530,6 +530,8 @@ void callback_groupmessage(Group_Chat *chat, void (*function)(Group_Chat *chat, Group_Chat *new_groupchat(Networking_Core *net) { + unix_time_update(); + if (net == 0) return 0; @@ -561,6 +563,7 @@ static void ping_close(Group_Chat *chat) void do_groupchat(Group_Chat *chat) { + unix_time_update(); ping_close(chat); } diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index a9aa77f9..9b8eff96 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -753,6 +753,8 @@ static void receive_crypto(Net_Crypto *c) */ Net_Crypto *new_net_crypto(Networking_Core *net) { + unix_time_update(); + if (net == NULL) return NULL; @@ -791,6 +793,7 @@ static void kill_timedout(Net_Crypto *c) /* Main loop. */ void do_net_crypto(Net_Crypto *c) { + unix_time_update(); do_lossless_udp(c->lossless_udp); kill_timedout(c); receive_crypto(c); -- cgit v1.2.3 From bbef18ab4e56fc727d4b629b6fd3882551eccdf5 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 25 Oct 2013 14:55:46 -0400 Subject: Update time before running functions for recieved packets. --- toxcore/network.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/toxcore/network.c b/toxcore/network.c index 53511df6..0f96083c 100644 --- a/toxcore/network.c +++ b/toxcore/network.c @@ -20,10 +20,10 @@ * along with Tox. If not, see . * */ - + #if (_WIN32_WINNT >= _WIN32_WINNT_WINXP) -#define _WIN32_WINNT 0x501 -#endif +#define _WIN32_WINNT 0x501 +#endif #ifdef HAVE_CONFIG_H #include "config.h" @@ -277,6 +277,8 @@ void networking_registerhandler(Networking_Core *net, uint8_t byte, packet_handl void networking_poll(Networking_Core *net) { + unix_time_update(); + IP_Port ip_port; uint8_t data[MAX_UDP_PACKET_SIZE]; uint32_t length; -- cgit v1.2.3 From 05a5184dc028789625831d2fd929759ea74846fb Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sat, 26 Oct 2013 18:11:55 -0400 Subject: Clarified a comment. --- toxcore/tox.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/toxcore/tox.h b/toxcore/tox.h index 2a26e7a6..0c7aa13c 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -521,7 +521,8 @@ uint64_t tox_file_dataremaining(Tox *tox, int friendnumber, uint8_t filenumber, void tox_bootstrap_from_ip(Tox *tox, tox_IP_Port ip_port, uint8_t *public_key); /* Resolves address into an IP address. If successful, sends a "get nodes" - * request to the given node with ip, port and public_key to setup connections + * request to the given node with ip, port (in network byte order, HINT: use htons()) + * and public_key to setup connections * * address can be a hostname or an IP address (IPv4 or IPv6). * if ipv6enabled is 0 (zero), the resolving sticks STRICTLY to IPv4 addresses -- cgit v1.2.3 From 3116336b836b73fa9ec1d8b3f8dc2c299f586801 Mon Sep 17 00:00:00 2001 From: Martijn Date: Sun, 27 Oct 2013 00:19:44 +0200 Subject: Small changes to A/V --- toxmsi/AV_codec.c | 6 ++++-- toxmsi/AV_codec.h | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/toxmsi/AV_codec.c b/toxmsi/AV_codec.c index 82e6a320..8a50c894 100644 --- a/toxmsi/AV_codec.c +++ b/toxmsi/AV_codec.c @@ -36,8 +36,8 @@ #include #include #include -#include -#include +#include +#include #include #include @@ -48,6 +48,8 @@ #include "phone.h" #include "AV_codec.h" +SDL_Surface *screen; + int display_received_frame(codec_state *cs, AVFrame *r_video_frame) { AVPicture pict; diff --git a/toxmsi/AV_codec.h b/toxmsi/AV_codec.h index 641cf486..bf5951d2 100644 --- a/toxmsi/AV_codec.h +++ b/toxmsi/AV_codec.h @@ -38,7 +38,7 @@ #include "../toxrtp/toxrtp.h" #include "../toxcore/tox.h" -#include +#include #include /* ffmpeg VP8 codec ID */ @@ -75,7 +75,7 @@ #define DEFAULT_WEBCAM "0" #endif -SDL_Surface *screen; +extern SDL_Surface *screen; typedef struct { SDL_Overlay *bmp; -- cgit v1.2.3 From f7040726a18a210f8330f00c0d23d1ca6a303d03 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sat, 26 Oct 2013 23:17:11 -0400 Subject: Increased port range. --- toxcore/network.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toxcore/network.h b/toxcore/network.h index 11d6be67..8b9b8b2f 100644 --- a/toxcore/network.h +++ b/toxcore/network.h @@ -94,7 +94,7 @@ typedef int sock_t; #define NET_PACKET_GROUP_CHATS 48 /* Group chats packet ID. */ #define TOX_PORTRANGE_FROM 33445 -#define TOX_PORTRANGE_TO 33455 +#define TOX_PORTRANGE_TO 33545 #define TOX_PORT_DEFAULT TOX_PORTRANGE_FROM typedef union { -- cgit v1.2.3 From d2ab13c61121fd14bbb2edc4406eaf807bbab3ec Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sun, 27 Oct 2013 20:25:31 -0400 Subject: Cleaned up some code/fixed some warnings. I'm sure nobody has any of the old save files anymore so I removed the functions. --- toxcore/Messenger.c | 140 +-------------------------------------------------- toxcore/net_crypto.c | 2 +- toxcore/tox.h | 2 +- 3 files changed, 3 insertions(+), 141 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 7da77541..be3d82e0 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -1890,144 +1890,6 @@ void wait_cleanup_messenger(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) -{ - return crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES - + sizeof(uint32_t) // nospam. - + sizeof(uint32_t) // DHT size. - + DHT_size(m->dht) // DHT itself. - + sizeof(uint32_t) // Friendlist size. - + sizeof(Friend) * m->numfriends // Friendlist itself. - + sizeof(uint16_t) // Own nickname length. - + m->name_length // Own nickname. - ; -} - -/* Save the messenger in data of size Messenger_size(). Old version without cookies. */ -static void Messenger_save_old(Messenger *m, uint8_t *data) -{ - save_keys(m->net_crypto, data); - data += crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES; - - uint32_t nospam = get_nospam(&(m->fr)); - memcpy(data, &nospam, sizeof(nospam)); - data += sizeof(nospam); - - uint32_t size = DHT_size(m->dht); - memcpy(data, &size, sizeof(size)); - data += sizeof(size); - DHT_save(m->dht, data); - data += size; - - size = sizeof(Friend) * m->numfriends; - memcpy(data, &size, sizeof(size)); - data += sizeof(size); - memcpy(data, m->friendlist, sizeof(Friend) * m->numfriends); - data += size; - - uint16_t small_size = m->name_length; - memcpy(data, &small_size, sizeof(small_size)); - data += sizeof(small_size); - memcpy(data, m->name, small_size); -} - -/* Load the messenger from data of size length. Old version without cookies. */ -static int Messenger_load_old(Messenger *m, uint8_t *data, uint32_t length) -{ - if (length == ~((uint32_t)0)) - return -1; - - /* BLOCK1: PUBKEY, SECKEY, NOSPAM, SIZE */ - if (length < crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t) * 2) - return -1; - - load_keys(m->net_crypto, data); - data += crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES; - length -= crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES; - - uint32_t nospam; - memcpy(&nospam, data, sizeof(nospam)); - set_nospam(&(m->fr), nospam); - data += sizeof(nospam); - length -= sizeof(nospam); - - uint32_t size; - - if (length < sizeof(size)) - return -1; - - memcpy(&size, data, sizeof(size)); - data += sizeof(size); - length -= sizeof(size); - - if (length < size) - return -1; - - if (DHT_load_old(m->dht, data, size) == -1) { -#ifdef DEBUG - fprintf(stderr, "Data file: Something wicked happened to the stored connections...\n"); - /* DO go on, friends/name still might be intact */ -#endif - } - - data += size; - length -= size; - - if (length < sizeof(size)) - return -1; - - memcpy(&size, data, sizeof(size)); - data += sizeof(size); - length -= sizeof(size); - - if (length < size) - return -1; - - if (!(size % sizeof(Friend))) { - uint16_t num = size / sizeof(Friend); - Friend *friend_list = (Friend *)data; - - uint32_t i; - - for (i = 0; i < num; ++i) { - if (friend_list[i].status >= 3) { - int fnum = m_addfriend_norequest(m, friend_list[i].client_id); - setfriendname(m, fnum, friend_list[i].name, friend_list[i].name_length); - /* set_friend_statusmessage(fnum, temp[i].statusmessage, temp[i].statusmessage_length); */ - } else if (friend_list[i].status != 0) { - /* TODO: This is not a good way to do this. */ - uint8_t address[FRIEND_ADDRESS_SIZE]; - id_copy(address, friend_list[i].client_id); - memcpy(address + crypto_box_PUBLICKEYBYTES, &(friend_list[i].friendrequest_nospam), sizeof(uint32_t)); - uint16_t checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum)); - memcpy(address + crypto_box_PUBLICKEYBYTES + sizeof(uint32_t), &checksum, sizeof(checksum)); - m_addfriend(m, address, friend_list[i].info, friend_list[i].info_size); - } - } - } - - data += size; - length -= size; - - uint16_t small_size; - - if (length < sizeof(small_size)) - return -1; - - memcpy(&small_size, data, sizeof(small_size)); - data += sizeof(small_size); - length -= sizeof(small_size); - - if (length < small_size) - return -1; - - setname(m, data, small_size); - - return 0; -} - - /* new messenger format for load/save, more robust and forward compatible */ #define MESSENGER_STATE_COOKIE_GLOBAL 0x15ed1b1e @@ -2176,7 +2038,7 @@ int messenger_load(Messenger *m, uint8_t *data, uint32_t length) return load_state(messenger_load_state_callback, m, data + cookie_len, length - cookie_len, MESSENGER_STATE_COOKIE_TYPE); else /* old state file */ - return Messenger_load_old(m, data, length); + return -1; } /* Return the number of friends in the instance m. diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 9b8eff96..3c7c114e 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -29,7 +29,7 @@ #endif #include "net_crypto.h" - +#include "util.h" static uint8_t crypt_connection_id_not_valid(Net_Crypto *c, int crypt_connection_id) { return (uint32_t)crypt_connection_id >= c->crypto_connections_length; diff --git a/toxcore/tox.h b/toxcore/tox.h index 0c7aa13c..5d3916b4 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -62,7 +62,7 @@ extern "C" { #define TOX_FRIEND_ADDRESS_SIZE (TOX_CLIENT_ID_SIZE + sizeof(uint32_t) + sizeof(uint16_t)) #define TOX_PORTRANGE_FROM 33445 -#define TOX_PORTRANGE_TO 33455 +#define TOX_PORTRANGE_TO 33545 #define TOX_PORT_DEFAULT TOX_PORTRANGE_FROM typedef union { -- cgit v1.2.3 From 4c6dc7a3b74ee720801d1259e4f498b19d343de6 Mon Sep 17 00:00:00 2001 From: Jin^eLD Date: Mon, 28 Oct 2013 13:15:59 +0100 Subject: Public headers should not have any internal references --- toxmsi/toxmsi.h | 2 +- toxrtp/toxrtp.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/toxmsi/toxmsi.h b/toxmsi/toxmsi.h index 69d5144a..d8985c64 100644 --- a/toxmsi/toxmsi.h +++ b/toxmsi/toxmsi.h @@ -28,7 +28,7 @@ #define _MSI_IMPL_H_ #include -#include "../toxcore/tox.h" +#include "tox.h" #include #define MCBTYPE void diff --git a/toxrtp/toxrtp.h b/toxrtp/toxrtp.h index 44717835..0aa89993 100644 --- a/toxrtp/toxrtp.h +++ b/toxrtp/toxrtp.h @@ -30,7 +30,7 @@ #define RTP_VERSION 2 #include -#include "../toxcore/tox.h" +#include "tox.h" #include /* Extension header flags */ #define RTP_EXT_TYPE_RESOLUTION 0x01 -- cgit v1.2.3 From 3d019fb115aafb5635c162a2cd0b61006bce9fc8 Mon Sep 17 00:00:00 2001 From: Martijn Date: Mon, 28 Oct 2013 13:51:48 +0100 Subject: added AV_codec.h to public headers --- toxmsi/AV_codec.h | 4 ++-- toxmsi/Makefile.inc | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/toxmsi/AV_codec.h b/toxmsi/AV_codec.h index bf5951d2..7eea39ae 100644 --- a/toxmsi/AV_codec.h +++ b/toxmsi/AV_codec.h @@ -35,8 +35,8 @@ #include #include #include -#include "../toxrtp/toxrtp.h" -#include "../toxcore/tox.h" +#include "toxrtp.h" +#include "tox.h" #include #include diff --git a/toxmsi/Makefile.inc b/toxmsi/Makefile.inc index 27678bc0..af8c7eef 100644 --- a/toxmsi/Makefile.inc +++ b/toxmsi/Makefile.inc @@ -3,7 +3,8 @@ if BUILD_AV lib_LTLIBRARIES += libtoxmsi.la libtoxmsi_la_include_HEADERS = \ - ../toxmsi/toxmsi.h + ../toxmsi/toxmsi.h \ + ../toxmsi/AV_codec.h libtoxmsi_la_includedir = $(includedir)/tox -- cgit v1.2.3 From 5971d8f7957fc887fbdcffcbd90012637a4c359f Mon Sep 17 00:00:00 2001 From: Martijn Date: Mon, 28 Oct 2013 14:19:38 +0100 Subject: renamed AV_codec to toxmedia --- toxmsi/AV_codec.c | 825 ---------------------------------------------------- toxmsi/AV_codec.h | 168 ----------- toxmsi/Makefile.inc | 5 +- toxmsi/phone.c | 2 +- toxmsi/phone.h | 2 +- toxmsi/toxmedia.c | 825 ++++++++++++++++++++++++++++++++++++++++++++++++++++ toxmsi/toxmedia.h | 168 +++++++++++ 7 files changed, 997 insertions(+), 998 deletions(-) delete mode 100644 toxmsi/AV_codec.c delete mode 100644 toxmsi/AV_codec.h create mode 100644 toxmsi/toxmedia.c create mode 100644 toxmsi/toxmedia.h diff --git a/toxmsi/AV_codec.c b/toxmsi/AV_codec.c deleted file mode 100644 index 8a50c894..00000000 --- a/toxmsi/AV_codec.c +++ /dev/null @@ -1,825 +0,0 @@ -/* AV_codec.c -// * - * Audio and video codec intitialisation, encoding/decoding and playback - * - * Copyright (C) 2013 Tox project All Rights Reserved. - * - * This file is part of Tox. - * - * Tox is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Tox is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Tox. If not, see . - * - */ - -/*----------------------------------------------------------------------------------*/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif /* HAVE_CONFIG_H */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "toxmsi.h" -#include "toxmsi_message.h" -#include "../toxrtp/toxrtp_message.h" -#include "../toxrtp/tests/test_helper.h" -#include "phone.h" -#include "AV_codec.h" - -SDL_Surface *screen; - -int display_received_frame(codec_state *cs, AVFrame *r_video_frame) -{ - AVPicture pict; - SDL_LockYUVOverlay(cs->video_picture.bmp); - - pict.data[0] = cs->video_picture.bmp->pixels[0]; - pict.data[1] = cs->video_picture.bmp->pixels[2]; - pict.data[2] = cs->video_picture.bmp->pixels[1]; - pict.linesize[0] = cs->video_picture.bmp->pitches[0]; - pict.linesize[1] = cs->video_picture.bmp->pitches[2]; - pict.linesize[2] = cs->video_picture.bmp->pitches[1]; - - /* Convert the image into YUV format that SDL uses */ - sws_scale(cs->sws_SDL_r_ctx, (uint8_t const * const *)r_video_frame->data, r_video_frame->linesize, 0, - cs->video_decoder_ctx->height, pict.data, pict.linesize ); - - SDL_UnlockYUVOverlay(cs->video_picture.bmp); - SDL_Rect rect; - rect.x = 0; - rect.y = 0; - rect.w = cs->video_decoder_ctx->width; - rect.h = cs->video_decoder_ctx->height; - SDL_DisplayYUVOverlay(cs->video_picture.bmp, &rect); - return 1; -} - -struct jitter_buffer { - rtp_msg_t **queue; - uint16_t capacity; - uint16_t size; - uint16_t front; - uint16_t rear; - uint8_t queue_ready; - uint16_t current_id; - uint32_t current_ts; - uint8_t id_set; -}; - -struct jitter_buffer *create_queue(int capacity) -{ - struct jitter_buffer *q; - q = (struct jitter_buffer *)calloc(sizeof(struct jitter_buffer),1); - q->queue = (rtp_msg_t **)calloc((sizeof(rtp_msg_t) * capacity),1); - int i = 0; - - for (i = 0; i < capacity; ++i) { - q->queue[i] = NULL; - } - - q->size = 0; - q->capacity = capacity; - q->front = 0; - q->rear = -1; - q->queue_ready = 0; - q->current_id = 0; - q->current_ts = 0; - q->id_set = 0; - return q; -} - -/* returns 1 if 'a' has a higher sequence number than 'b' */ -uint8_t sequence_number_older(uint16_t sn_a, uint16_t sn_b, uint32_t ts_a, uint32_t ts_b) -{ - /* should be stable enough */ - return (sn_a > sn_b || ts_a > ts_b); -} - -/* success is 0 when there is nothing to dequeue, 1 when there's a good packet, 2 when there's a lost packet */ -rtp_msg_t *dequeue(struct jitter_buffer *q, int *success) -{ - if (q->size == 0 || q->queue_ready == 0) { - q->queue_ready = 0; - *success = 0; - return NULL; - } - - int front = q->front; - - if (q->id_set == 0) { - q->current_id = q->queue[front]->_header->_sequence_number; - q->current_ts = q->queue[front]->_header->_timestamp; - q->id_set = 1; - } else { - int next_id = q->queue[front]->_header->_sequence_number; - int next_ts = q->queue[front]->_header->_timestamp; - - /* if this packet is indeed the expected packet */ - if (next_id == (q->current_id + 1) % _MAX_SEQU_NUM) { - q->current_id = next_id; - q->current_ts = next_ts; - } else { - if (sequence_number_older(next_id, q->current_id, next_ts, q->current_ts)) { - printf("nextid: %d current: %d\n", next_id, q->current_id); - q->current_id = (q->current_id + 1) % _MAX_SEQU_NUM; - *success = 2; /* tell the decoder the packet is lost */ - return NULL; - } else { - /* packet too old */ - printf("packet too old\n"); - *success = 0; - return NULL; - } - } - } - - q->size--; - q->front++; - - if (q->front == q->capacity) - q->front = 0; - - *success = 1; - q->current_id = q->queue[front]->_header->_sequence_number; - q->current_ts = q->queue[front]->_header->_timestamp; - return q->queue[front]; -} - -int empty_queue(struct jitter_buffer *q) -{ - while (q->size > 0) { - q->size--; - /* FIXME: */ - /* rtp_free_msg(cs->_rtp_video, q->queue[q->front]); */ - q->front++; - - if (q->front == q->capacity) - q->front = 0; - } - - q->id_set = 0; - q->queue_ready = 0; - return 0; -} - -int queue(struct jitter_buffer *q, rtp_msg_t *pk) -{ - if (q->size == q->capacity) { - printf("buffer full, emptying buffer...\n"); - empty_queue(q); - return 0; - } - - if (q->size > 8) - q->queue_ready = 1; - - ++q->size; - ++q->rear; - - if (q->rear == q->capacity) - q->rear = 0; - - q->queue[q->rear] = pk; - - int a; - int b; - int j; - a = q->rear; - - for (j = 0; j < q->size - 1; ++j) { - b = a - 1; - - if (b < 0) - b += q->capacity; - - if (sequence_number_older(q->queue[b]->_header->_sequence_number, q->queue[a]->_header->_sequence_number, - q->queue[b]->_header->_timestamp, q->queue[a]->_header->_timestamp)) { - rtp_msg_t *temp; - temp = q->queue[a]; - q->queue[a] = q->queue[b]; - q->queue[b] = temp; - printf("had to swap\n"); - } else { - break; - } - - a -= 1; - - if (a < 0) - a += q->capacity; - } - - if (pk) - return 1; - - return 0; -} - -int init_receive_audio(codec_state *cs) -{ - int err = OPUS_OK; - cs->audio_decoder = opus_decoder_create(48000, 1, &err); - opus_decoder_init(cs->audio_decoder, 48000, 1); - printf("init audio decoder successful\n"); - return 1; -} - -int init_receive_video(codec_state *cs) -{ - cs->video_decoder = avcodec_find_decoder(VIDEO_CODEC); - - if (!cs->video_decoder) { - printf("init video_decoder failed\n"); - return 0; - } - - cs->video_decoder_ctx = avcodec_alloc_context3(cs->video_decoder); - - if (!cs->video_decoder_ctx) { - printf("init video_decoder_ctx failed\n"); - return 0; - } - - if (avcodec_open2(cs->video_decoder_ctx, cs->video_decoder, NULL) < 0) { - printf("opening video decoder failed\n"); - return 0; - } - - printf("init video decoder successful\n"); - return 1; -} - -int init_send_video(codec_state *cs) -{ - cs->video_input_format = av_find_input_format(VIDEO_DRIVER); - - if (avformat_open_input(&cs->video_format_ctx, DEFAULT_WEBCAM, cs->video_input_format, NULL) != 0) { - printf("opening video_input_format failed\n"); - return 0; - } - - avformat_find_stream_info(cs->video_format_ctx, NULL); - av_dump_format(cs->video_format_ctx, 0, DEFAULT_WEBCAM, 0); - - int i; - - for (i = 0; i < cs->video_format_ctx->nb_streams; ++i) { - if (cs->video_format_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { - cs->video_stream = i; - break; - } - } - - cs->webcam_decoder_ctx = cs->video_format_ctx->streams[cs->video_stream]->codec; - cs->webcam_decoder = avcodec_find_decoder(cs->webcam_decoder_ctx->codec_id); - - if (cs->webcam_decoder == NULL) { - printf("Unsupported codec\n"); - return 0; - } - - if (cs->webcam_decoder_ctx == NULL) { - printf("init webcam_decoder_ctx failed\n"); - return 0; - } - - if (avcodec_open2(cs->webcam_decoder_ctx, cs->webcam_decoder, NULL) < 0) { - printf("opening webcam decoder failed\n"); - return 0; - } - - cs->video_encoder = avcodec_find_encoder(VIDEO_CODEC); - - if (!cs->video_encoder) { - printf("init video_encoder failed\n"); - return 0; - } - - cs->video_encoder_ctx = avcodec_alloc_context3(cs->video_encoder); - - if (!cs->video_encoder_ctx) { - printf("init video_encoder_ctx failed\n"); - return 0; - } - - cs->video_encoder_ctx->bit_rate = VIDEO_BITRATE; - cs->video_encoder_ctx->rc_min_rate = cs->video_encoder_ctx->rc_max_rate = cs->video_encoder_ctx->bit_rate; - av_opt_set_double(cs->video_encoder_ctx->priv_data, "max-intra-rate", 90, 0); - av_opt_set(cs->video_encoder_ctx->priv_data, "quality", "realtime", 0); - - cs->video_encoder_ctx->thread_count = 4; - cs->video_encoder_ctx->rc_buffer_aggressivity = 0.95; - cs->video_encoder_ctx->rc_buffer_size = VIDEO_BITRATE * 6; - cs->video_encoder_ctx->profile = 3; - cs->video_encoder_ctx->qmax = 54; - cs->video_encoder_ctx->qmin = 4; - AVRational myrational = {1, 25}; - cs->video_encoder_ctx->time_base = myrational; - cs->video_encoder_ctx->gop_size = 99999; - cs->video_encoder_ctx->pix_fmt = PIX_FMT_YUV420P; - cs->video_encoder_ctx->width = cs->webcam_decoder_ctx->width; - cs->video_encoder_ctx->height = cs->webcam_decoder_ctx->height; - - if (avcodec_open2(cs->video_encoder_ctx, cs->video_encoder, NULL) < 0) { - printf("opening video encoder failed\n"); - return 0; - } - - printf("init video encoder successful\n"); - return 1; -} - -int init_send_audio(codec_state *cs) -{ - cs->support_send_audio = 0; - - const ALchar *pDeviceList = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER); - int i = 0; - const ALchar *device_names[20]; - - if (pDeviceList) { - printf("\nAvailable Capture Devices are:\n"); - - while (*pDeviceList) { - device_names[i] = pDeviceList; - printf("%d) %s\n", i, device_names[i]); - pDeviceList += strlen(pDeviceList) + 1; - ++i; - } - } - - printf("enter capture device number: \n"); - char dev[2]; - fgets(dev, sizeof(dev), stdin); - cs->audio_capture_device = alcCaptureOpenDevice(device_names[dev[0] - 48], AUDIO_SAMPLE_RATE, AL_FORMAT_MONO16, - AUDIO_FRAME_SIZE * 4); - - if (alcGetError(cs->audio_capture_device) != AL_NO_ERROR) { - printf("could not start capture device! %d\n", alcGetError(cs->audio_capture_device)); - return 0; - } - - int err = OPUS_OK; - cs->audio_bitrate = AUDIO_BITRATE; - cs->audio_encoder = opus_encoder_create(AUDIO_SAMPLE_RATE, 1, OPUS_APPLICATION_VOIP, &err); - err = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_BITRATE(cs->audio_bitrate)); - err = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_COMPLEXITY(10)); - err = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE)); - - opus_encoder_init(cs->audio_encoder, AUDIO_SAMPLE_RATE, 1, OPUS_APPLICATION_VOIP); - - int nfo; - err = opus_encoder_ctl(cs->audio_encoder, OPUS_GET_LOOKAHEAD(&nfo)); - /* printf("Encoder lookahead delay : %d\n", nfo); */ - printf("init audio encoder successful\n"); - - return 1; -} - -int init_encoder(codec_state *cs) -{ - avdevice_register_all(); - avcodec_register_all(); - avdevice_register_all(); - av_register_all(); - - pthread_mutex_init(&cs->rtp_msg_mutex_lock, NULL); - pthread_mutex_init(&cs->avcodec_mutex_lock, NULL); - - cs->support_send_video = init_send_video(cs); - cs->support_send_audio = init_send_audio(cs); - - cs->send_audio = 1; - cs->send_video = 1; - - return 1; -} - -int init_decoder(codec_state *cs) -{ - avdevice_register_all(); - avcodec_register_all(); - avdevice_register_all(); - av_register_all(); - - cs->receive_video = 0; - cs->receive_audio = 0; - - cs->support_receive_video = init_receive_video(cs); - cs->support_receive_audio = init_receive_audio(cs); - - cs->receive_audio = 1; - cs->receive_video = 1; - - return 1; -} - -int video_encoder_refresh(codec_state *cs, int bps) -{ - if (cs->video_encoder_ctx) - avcodec_close(cs->video_encoder_ctx); - - cs->video_encoder = avcodec_find_encoder(VIDEO_CODEC); - - if (!cs->video_encoder) { - printf("init video_encoder failed\n"); - return -1; - } - - cs->video_encoder_ctx = avcodec_alloc_context3(cs->video_encoder); - - if (!cs->video_encoder_ctx) { - printf("init video_encoder_ctx failed\n"); - return -1; - } - - cs->video_encoder_ctx->bit_rate = bps; - cs->video_encoder_ctx->rc_min_rate = cs->video_encoder_ctx->rc_max_rate = cs->video_encoder_ctx->bit_rate; - av_opt_set_double(cs->video_encoder_ctx->priv_data, "max-intra-rate", 90, 0); - av_opt_set(cs->video_encoder_ctx->priv_data, "quality", "realtime", 0); - - cs->video_encoder_ctx->thread_count = 4; - cs->video_encoder_ctx->rc_buffer_aggressivity = 0.95; - cs->video_encoder_ctx->rc_buffer_size = bps * 6; - cs->video_encoder_ctx->profile = 0; - cs->video_encoder_ctx->qmax = 54; - cs->video_encoder_ctx->qmin = 4; - AVRational myrational = {1, 25}; - cs->video_encoder_ctx->time_base = myrational; - cs->video_encoder_ctx->gop_size = 99999; - cs->video_encoder_ctx->pix_fmt = PIX_FMT_YUV420P; - cs->video_encoder_ctx->width = cs->webcam_decoder_ctx->width; - cs->video_encoder_ctx->height = cs->webcam_decoder_ctx->height; - - if (avcodec_open2(cs->video_encoder_ctx, cs->video_encoder, NULL) < 0) { - printf("opening video encoder failed\n"); - return -1; - } - return 0; -} - -void *encode_video_thread(void *arg) -{ - codec_state *cs = (codec_state *)arg; - AVPacket pkt1, *packet = &pkt1; - int p = 0; - int err; - int got_packet; - rtp_msg_t *s_video_msg; - int video_frame_finished; - AVFrame *s_video_frame; - AVFrame *webcam_frame; - s_video_frame = avcodec_alloc_frame(); - webcam_frame = avcodec_alloc_frame(); - AVPacket enc_video_packet; - - uint8_t *buffer; - int numBytes; - /* Determine required buffer size and allocate buffer */ - numBytes = avpicture_get_size(PIX_FMT_YUV420P, cs->webcam_decoder_ctx->width, cs->webcam_decoder_ctx->height); - buffer = (uint8_t *)av_calloc(numBytes * sizeof(uint8_t),1); - avpicture_fill((AVPicture *)s_video_frame, buffer, PIX_FMT_YUV420P, cs->webcam_decoder_ctx->width, - cs->webcam_decoder_ctx->height); - cs->sws_ctx = sws_getContext(cs->webcam_decoder_ctx->width, cs->webcam_decoder_ctx->height, - cs->webcam_decoder_ctx->pix_fmt, cs->webcam_decoder_ctx->width, cs->webcam_decoder_ctx->height, PIX_FMT_YUV420P, - SWS_BILINEAR, NULL, NULL, NULL); - - while (!cs->quit && cs->send_video) { - - if (av_read_frame(cs->video_format_ctx, packet) < 0) { - printf("error reading frame\n"); - - if (cs->video_format_ctx->pb->error != 0) - break; - - continue; - } - - if (packet->stream_index == cs->video_stream) { - if (avcodec_decode_video2(cs->webcam_decoder_ctx, webcam_frame, &video_frame_finished, packet) < 0) { - printf("couldn't decode\n"); - continue; - } - - av_free_packet(packet); - sws_scale(cs->sws_ctx, (uint8_t const * const *)webcam_frame->data, webcam_frame->linesize, 0, - cs->webcam_decoder_ctx->height, s_video_frame->data, s_video_frame->linesize); - /* create a new I-frame every 60 frames */ - ++p; - - if (p == 60) { - - s_video_frame->pict_type = AV_PICTURE_TYPE_BI ; - } else if (p == 61) { - s_video_frame->pict_type = AV_PICTURE_TYPE_I ; - p = 0; - } else { - s_video_frame->pict_type = AV_PICTURE_TYPE_P ; - } - - if (video_frame_finished) { - err = avcodec_encode_video2(cs->video_encoder_ctx, &enc_video_packet, s_video_frame, &got_packet); - - if (err < 0) { - printf("could not encode video frame\n"); - continue; - } - - if (!got_packet) { - continue; - } - - pthread_mutex_lock(&cs->rtp_msg_mutex_lock); - THREADLOCK() - - if (!enc_video_packet.data) fprintf(stderr, "video packet data is NULL\n"); - - s_video_msg = rtp_msg_new ( cs->_rtp_video, enc_video_packet.data, enc_video_packet.size ) ; - - if (!s_video_msg) { - printf("invalid message\n"); - } - - rtp_send_msg ( cs->_rtp_video, s_video_msg, cs->_networking ); - THREADUNLOCK() - pthread_mutex_unlock(&cs->rtp_msg_mutex_lock); - av_free_packet(&enc_video_packet); - } - } else { - av_free_packet(packet); - } - } - - /* clean up codecs */ - pthread_mutex_lock(&cs->avcodec_mutex_lock); - av_free(buffer); - av_free(webcam_frame); - av_free(s_video_frame); - sws_freeContext(cs->sws_ctx); - avcodec_close(cs->webcam_decoder_ctx); - avcodec_close(cs->video_encoder_ctx); - pthread_mutex_unlock(&cs->avcodec_mutex_lock); - pthread_exit ( NULL ); -} - -void *encode_audio_thread(void *arg) -{ - codec_state *cs = (codec_state *)arg; - rtp_msg_t *s_audio_msg; - unsigned char encoded_data[4096]; - int encoded_size = 0; - int16_t frame[4096]; - int frame_size = AUDIO_FRAME_SIZE; - ALint sample = 0; - alcCaptureStart(cs->audio_capture_device); - - while (!cs->quit && cs->send_audio) { - alcGetIntegerv(cs->audio_capture_device, ALC_CAPTURE_SAMPLES, (ALCsizei)sizeof(ALint), &sample); - - if (sample >= frame_size) { - alcCaptureSamples(cs->audio_capture_device, frame, frame_size); - encoded_size = opus_encode(cs->audio_encoder, frame, frame_size, encoded_data, 480); - - if (encoded_size <= 0) { - printf("Could not encode audio packet\n"); - } else { - pthread_mutex_lock(&cs->rtp_msg_mutex_lock); - THREADLOCK() - rtp_set_payload_type(cs->_rtp_audio, 96); - s_audio_msg = rtp_msg_new (cs->_rtp_audio, encoded_data, encoded_size) ; - rtp_send_msg ( cs->_rtp_audio, s_audio_msg, cs->_networking ); - pthread_mutex_unlock(&cs->rtp_msg_mutex_lock); - THREADUNLOCK() - } - } else { - usleep(1000); - } - } - - /* clean up codecs */ - pthread_mutex_lock(&cs->avcodec_mutex_lock); - alcCaptureStop(cs->audio_capture_device); - alcCaptureCloseDevice(cs->audio_capture_device); - - pthread_mutex_unlock(&cs->avcodec_mutex_lock); - pthread_exit ( NULL ); -} - - -int video_decoder_refresh(codec_state *cs, int width, int height) -{ - printf("need to refresh\n"); - screen = SDL_SetVideoMode(width, height, 0, 0); - - if (cs->video_picture.bmp) - SDL_FreeYUVOverlay(cs->video_picture.bmp); - - cs->video_picture.bmp = SDL_CreateYUVOverlay(width, height, SDL_YV12_OVERLAY, screen); - cs->sws_SDL_r_ctx = sws_getContext(width, height, cs->video_decoder_ctx->pix_fmt, width, height, PIX_FMT_YUV420P, - SWS_BILINEAR, NULL, NULL, NULL); - return 1; -} - -void *decode_video_thread(void *arg) -{ - codec_state *cs = (codec_state *)arg; - cs->video_stream = 0; - rtp_msg_t *r_msg; - int dec_frame_finished; - AVFrame *r_video_frame; - r_video_frame = avcodec_alloc_frame(); - AVPacket dec_video_packet; - av_new_packet (&dec_video_packet, 65536); - int width = 0; - int height = 0; - - while (!cs->quit && cs->receive_video) { - r_msg = rtp_recv_msg ( cs->_rtp_video ); - - if (r_msg) { - memcpy(dec_video_packet.data, r_msg->_data, r_msg->_length); - dec_video_packet.size = r_msg->_length; - avcodec_decode_video2(cs->video_decoder_ctx, r_video_frame, &dec_frame_finished, &dec_video_packet); - - if (dec_frame_finished) { - if (cs->video_decoder_ctx->width != width || cs->video_decoder_ctx->height != height) { - width = cs->video_decoder_ctx->width; - height = cs->video_decoder_ctx->height; - printf("w: %d h%d \n", width, height); - video_decoder_refresh(cs, width, height); - } - - display_received_frame(cs, r_video_frame); - } else { - /* TODO: request the sender to create a new i-frame immediatly */ - printf("bad video packet\n"); - } - - rtp_free_msg(cs->_rtp_video, r_msg); - } - - usleep(1000); - } - - printf("vend\n"); - /* clean up codecs */ - pthread_mutex_lock(&cs->avcodec_mutex_lock); - av_free(r_video_frame); - avcodec_close(cs->video_decoder_ctx); - pthread_mutex_unlock(&cs->avcodec_mutex_lock); - pthread_exit ( NULL ); -} - -void *decode_audio_thread(void *arg) -{ - codec_state *cs = (codec_state *)arg; - rtp_msg_t *r_msg; - - int frame_size = AUDIO_FRAME_SIZE; - int data_size; - - ALCdevice *dev; - ALCcontext *ctx; - ALuint source, *buffers; - dev = alcOpenDevice(NULL); - ctx = alcCreateContext(dev, NULL); - alcMakeContextCurrent(ctx); - int openal_buffers = 5; - - buffers = calloc(sizeof(ALuint) * openal_buffers,1); - alGenBuffers(openal_buffers, buffers); - alGenSources((ALuint)1, &source); - alSourcei(source, AL_LOOPING, AL_FALSE); - - ALuint buffer; - ALint val; - - ALenum error; - uint16_t zeros[frame_size]; - int i; - - for (i = 0; i < frame_size; i++) { - zeros[i] = 0; - } - - for (i = 0; i < openal_buffers; ++i) { - alBufferData(buffers[i], AL_FORMAT_MONO16, zeros, frame_size, 48000); - } - - alSourceQueueBuffers(source, openal_buffers, buffers); - alSourcePlay(source); - - if (alGetError() != AL_NO_ERROR) { - fprintf(stderr, "Error starting audio\n"); - cs->quit = 1; - } - - struct jitter_buffer *j_buf = NULL; - - j_buf = create_queue(20); - - int success = 0; - - int dec_frame_len; - - opus_int16 PCM[frame_size]; - - while (!cs->quit && cs->receive_audio) { - THREADLOCK() - r_msg = rtp_recv_msg ( cs->_rtp_audio ); - - if (r_msg) { - /* push the packet into the queue */ - queue(j_buf, r_msg); - } - - /* grab a packet from the queue */ - success = 0; - alGetSourcei(source, AL_BUFFERS_PROCESSED, &val); - - if (val > 0) - r_msg = dequeue(j_buf, &success); - - if (success > 0) { - /* good packet */ - if (success == 1) { - dec_frame_len = opus_decode(cs->audio_decoder, r_msg->_data, r_msg->_length, PCM, frame_size, 0); - rtp_free_msg(cs->_rtp_audio, r_msg); - } - - /* lost packet */ - if (success == 2) { - printf("lost packet\n"); - dec_frame_len = opus_decode(cs->audio_decoder, NULL, 0, PCM, frame_size, 1); - } - - if (dec_frame_len > 0) { - alGetSourcei(source, AL_BUFFERS_PROCESSED, &val); - - if (val <= 0) - continue; - - alSourceUnqueueBuffers(source, 1, &buffer); - data_size = av_samples_get_buffer_size(NULL, 1, dec_frame_len, AV_SAMPLE_FMT_S16, 1); - alBufferData(buffer, AL_FORMAT_MONO16, PCM, data_size, 48000); - int error = alGetError(); - - if (error != AL_NO_ERROR) { - fprintf(stderr, "Error setting buffer %d\n", error); - break; - } - - alSourceQueueBuffers(source, 1, &buffer); - - if (alGetError() != AL_NO_ERROR) { - fprintf(stderr, "error: could not buffer audio\n"); - break; - } - - alGetSourcei(source, AL_SOURCE_STATE, &val); - - if (val != AL_PLAYING) - alSourcePlay(source); - - - } - } - - THREADUNLOCK() - usleep(1000); - } - - /* clean up codecs */ - pthread_mutex_lock(&cs->avcodec_mutex_lock); - - /* clean up openal */ - alDeleteSources(1, &source); - alDeleteBuffers(openal_buffers, buffers); - alcMakeContextCurrent(NULL); - alcDestroyContext(ctx); - alcCloseDevice(dev); - pthread_mutex_unlock(&cs->avcodec_mutex_lock); - pthread_exit ( NULL ); -} diff --git a/toxmsi/AV_codec.h b/toxmsi/AV_codec.h deleted file mode 100644 index 7eea39ae..00000000 --- a/toxmsi/AV_codec.h +++ /dev/null @@ -1,168 +0,0 @@ -/* AV_codec.h - * - * Audio and video codec intitialisation, encoding/decoding and playback - * - * Copyright (C) 2013 Tox project All Rights Reserved. - * - * This file is part of Tox. - * - * Tox is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Tox is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Tox. If not, see . - * - */ - -/*----------------------------------------------------------------------------------*/ -#ifndef _AVCODEC_H_ -#define _AVCODEC_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "toxrtp.h" -#include "tox.h" - -#include -#include - -/* ffmpeg VP8 codec ID */ -#define VIDEO_CODEC AV_CODEC_ID_VP8 - -/* ffmpeg Opus codec ID */ -#define AUDIO_CODEC AV_CODEC_ID_OPUS - -/* default video bitrate in bytes/s */ -#define VIDEO_BITRATE 10*1000 - -/* default audio bitrate in bytes/s */ -#define AUDIO_BITRATE 64000 - -/* audio frame duration in miliseconds */ -#define AUDIO_FRAME_DURATION 20 - -/* audio sample rate recommended to be 48kHz for Opus */ -#define AUDIO_SAMPLE_RATE 48000 - -/* the amount of samples in one audio frame */ -#define AUDIO_FRAME_SIZE AUDIO_SAMPLE_RATE*AUDIO_FRAME_DURATION/1000 - -/* the quit event for SDL */ -#define FF_QUIT_EVENT (SDL_USEREVENT + 2) - -#ifdef __linux__ -#define VIDEO_DRIVER "video4linux2" -#define DEFAULT_WEBCAM "/dev/video0" -#endif - -#ifdef WIN32 -#define VIDEO_DRIVER "vfwcap" -#define DEFAULT_WEBCAM "0" -#endif - -extern SDL_Surface *screen; - -typedef struct { - SDL_Overlay *bmp; - int width, height; -} VideoPicture; - - -typedef struct { - uint8_t send_audio; - uint8_t receive_audio; - uint8_t send_video; - uint8_t receive_video; - - uint8_t support_send_audio; - uint8_t support_send_video; - uint8_t support_receive_audio; - uint8_t support_receive_video; - - /* video encoding */ - AVInputFormat *video_input_format; - AVFormatContext *video_format_ctx; - uint8_t video_stream; - AVCodecContext *webcam_decoder_ctx; - AVCodec *webcam_decoder; - AVCodecContext *video_encoder_ctx; - AVCodec *video_encoder; - - /* video decoding */ - AVCodecContext *video_decoder_ctx; - AVCodec *video_decoder; - - /* audio encoding */ - ALCdevice *audio_capture_device; - OpusEncoder *audio_encoder; - int audio_bitrate; - - /* audio decoding */ - OpusDecoder *audio_decoder; - - uint8_t req_video_refresh; - - /* context for converting image format to something SDL can use*/ - struct SwsContext *sws_SDL_r_ctx; - - /* context for converting webcam image format to something the video encoder can use */ - struct SwsContext *sws_ctx; - - /* rendered video picture, ready for display */ - VideoPicture video_picture; - - rtp_session_t *_rtp_video; - rtp_session_t *_rtp_audio; - int socket; - Networking_Core *_networking; - - pthread_t encode_audio_thread; - pthread_t encode_video_thread; - - pthread_t decode_audio_thread; - pthread_t decode_video_thread; - - pthread_mutex_t rtp_msg_mutex_lock; - pthread_mutex_t avcodec_mutex_lock; - - uint8_t quit; - SDL_Event SDL_event; - - msi_session_t *_msi; - uint32_t _frame_rate; - uint16_t _send_port, _recv_port; - int _tox_sock; - //pthread_id _medialoop_id; - -} codec_state; - -int display_received_frame(codec_state *cs, AVFrame *r_video_frame); -int init_receive_audio(codec_state *cs); -int init_decoder(codec_state *cs); -int init_send_video(codec_state *cs); -int init_send_audio(codec_state *cs); -int init_encoder(codec_state *cs); -int video_encoder_refresh(codec_state *cs, int bps); -void *encode_video_thread(void *arg); -void *encode_audio_thread(void *arg); -int video_decoder_refresh(codec_state *cs, int width, int height); -int handle_rtp_video_packet(codec_state *cs, rtp_msg_t *r_msg); -void *decode_video_thread(void *arg); -void *decode_audio_thread(void *arg); - -#endif diff --git a/toxmsi/Makefile.inc b/toxmsi/Makefile.inc index af8c7eef..7d620e70 100644 --- a/toxmsi/Makefile.inc +++ b/toxmsi/Makefile.inc @@ -4,7 +4,7 @@ lib_LTLIBRARIES += libtoxmsi.la libtoxmsi_la_include_HEADERS = \ ../toxmsi/toxmsi.h \ - ../toxmsi/AV_codec.h + ../toxmsi/toxmedia.h libtoxmsi_la_includedir = $(includedir)/tox @@ -36,8 +36,7 @@ libtoxmsi_la_LIBS = $(NACL_LIBS) noinst_PROGRAMS += phone phone_SOURCES = ../toxmsi/phone.c \ - ../toxmsi/AV_codec.h \ - ../toxmsi/AV_codec.c + ../toxmsi/toxmedia.c phone_CFLAGS = -I../toxcore \ -I../toxrtp \ diff --git a/toxmsi/phone.c b/toxmsi/phone.c index f14d0323..432be94c 100644 --- a/toxmsi/phone.c +++ b/toxmsi/phone.c @@ -16,7 +16,7 @@ #include /* #include Can this be removed? */ #include -#include "AV_codec.h" +#include "toxmedia.h" diff --git a/toxmsi/phone.h b/toxmsi/phone.h index d661dcfd..f96aac73 100644 --- a/toxmsi/phone.h +++ b/toxmsi/phone.h @@ -8,7 +8,7 @@ #include "../toxrtp/tests/test_helper.h" #include #include -#include "AV_codec.h" +#include "toxmedia.h" /* Define client version */ #define _USERAGENT "tox_phone-v.0.2.1" diff --git a/toxmsi/toxmedia.c b/toxmsi/toxmedia.c new file mode 100644 index 00000000..4c9f5261 --- /dev/null +++ b/toxmsi/toxmedia.c @@ -0,0 +1,825 @@ +/* AV_codec.c +// * + * Audio and video codec intitialisation, encoding/decoding and playback + * + * Copyright (C) 2013 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ + +/*----------------------------------------------------------------------------------*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "toxmsi.h" +#include "toxmsi_message.h" +#include "../toxrtp/toxrtp_message.h" +#include "../toxrtp/tests/test_helper.h" +#include "phone.h" +#include "toxmedia.h" + +SDL_Surface *screen; + +int display_received_frame(codec_state *cs, AVFrame *r_video_frame) +{ + AVPicture pict; + SDL_LockYUVOverlay(cs->video_picture.bmp); + + pict.data[0] = cs->video_picture.bmp->pixels[0]; + pict.data[1] = cs->video_picture.bmp->pixels[2]; + pict.data[2] = cs->video_picture.bmp->pixels[1]; + pict.linesize[0] = cs->video_picture.bmp->pitches[0]; + pict.linesize[1] = cs->video_picture.bmp->pitches[2]; + pict.linesize[2] = cs->video_picture.bmp->pitches[1]; + + /* Convert the image into YUV format that SDL uses */ + sws_scale(cs->sws_SDL_r_ctx, (uint8_t const * const *)r_video_frame->data, r_video_frame->linesize, 0, + cs->video_decoder_ctx->height, pict.data, pict.linesize ); + + SDL_UnlockYUVOverlay(cs->video_picture.bmp); + SDL_Rect rect; + rect.x = 0; + rect.y = 0; + rect.w = cs->video_decoder_ctx->width; + rect.h = cs->video_decoder_ctx->height; + SDL_DisplayYUVOverlay(cs->video_picture.bmp, &rect); + return 1; +} + +struct jitter_buffer { + rtp_msg_t **queue; + uint16_t capacity; + uint16_t size; + uint16_t front; + uint16_t rear; + uint8_t queue_ready; + uint16_t current_id; + uint32_t current_ts; + uint8_t id_set; +}; + +struct jitter_buffer *create_queue(int capacity) +{ + struct jitter_buffer *q; + q = (struct jitter_buffer *)calloc(sizeof(struct jitter_buffer),1); + q->queue = (rtp_msg_t **)calloc((sizeof(rtp_msg_t) * capacity),1); + int i = 0; + + for (i = 0; i < capacity; ++i) { + q->queue[i] = NULL; + } + + q->size = 0; + q->capacity = capacity; + q->front = 0; + q->rear = -1; + q->queue_ready = 0; + q->current_id = 0; + q->current_ts = 0; + q->id_set = 0; + return q; +} + +/* returns 1 if 'a' has a higher sequence number than 'b' */ +uint8_t sequence_number_older(uint16_t sn_a, uint16_t sn_b, uint32_t ts_a, uint32_t ts_b) +{ + /* should be stable enough */ + return (sn_a > sn_b || ts_a > ts_b); +} + +/* success is 0 when there is nothing to dequeue, 1 when there's a good packet, 2 when there's a lost packet */ +rtp_msg_t *dequeue(struct jitter_buffer *q, int *success) +{ + if (q->size == 0 || q->queue_ready == 0) { + q->queue_ready = 0; + *success = 0; + return NULL; + } + + int front = q->front; + + if (q->id_set == 0) { + q->current_id = q->queue[front]->_header->_sequence_number; + q->current_ts = q->queue[front]->_header->_timestamp; + q->id_set = 1; + } else { + int next_id = q->queue[front]->_header->_sequence_number; + int next_ts = q->queue[front]->_header->_timestamp; + + /* if this packet is indeed the expected packet */ + if (next_id == (q->current_id + 1) % _MAX_SEQU_NUM) { + q->current_id = next_id; + q->current_ts = next_ts; + } else { + if (sequence_number_older(next_id, q->current_id, next_ts, q->current_ts)) { + printf("nextid: %d current: %d\n", next_id, q->current_id); + q->current_id = (q->current_id + 1) % _MAX_SEQU_NUM; + *success = 2; /* tell the decoder the packet is lost */ + return NULL; + } else { + /* packet too old */ + printf("packet too old\n"); + *success = 0; + return NULL; + } + } + } + + q->size--; + q->front++; + + if (q->front == q->capacity) + q->front = 0; + + *success = 1; + q->current_id = q->queue[front]->_header->_sequence_number; + q->current_ts = q->queue[front]->_header->_timestamp; + return q->queue[front]; +} + +int empty_queue(struct jitter_buffer *q) +{ + while (q->size > 0) { + q->size--; + /* FIXME: */ + /* rtp_free_msg(cs->_rtp_video, q->queue[q->front]); */ + q->front++; + + if (q->front == q->capacity) + q->front = 0; + } + + q->id_set = 0; + q->queue_ready = 0; + return 0; +} + +int queue(struct jitter_buffer *q, rtp_msg_t *pk) +{ + if (q->size == q->capacity) { + printf("buffer full, emptying buffer...\n"); + empty_queue(q); + return 0; + } + + if (q->size > 8) + q->queue_ready = 1; + + ++q->size; + ++q->rear; + + if (q->rear == q->capacity) + q->rear = 0; + + q->queue[q->rear] = pk; + + int a; + int b; + int j; + a = q->rear; + + for (j = 0; j < q->size - 1; ++j) { + b = a - 1; + + if (b < 0) + b += q->capacity; + + if (sequence_number_older(q->queue[b]->_header->_sequence_number, q->queue[a]->_header->_sequence_number, + q->queue[b]->_header->_timestamp, q->queue[a]->_header->_timestamp)) { + rtp_msg_t *temp; + temp = q->queue[a]; + q->queue[a] = q->queue[b]; + q->queue[b] = temp; + printf("had to swap\n"); + } else { + break; + } + + a -= 1; + + if (a < 0) + a += q->capacity; + } + + if (pk) + return 1; + + return 0; +} + +int init_receive_audio(codec_state *cs) +{ + int err = OPUS_OK; + cs->audio_decoder = opus_decoder_create(48000, 1, &err); + opus_decoder_init(cs->audio_decoder, 48000, 1); + printf("init audio decoder successful\n"); + return 1; +} + +int init_receive_video(codec_state *cs) +{ + cs->video_decoder = avcodec_find_decoder(VIDEO_CODEC); + + if (!cs->video_decoder) { + printf("init video_decoder failed\n"); + return 0; + } + + cs->video_decoder_ctx = avcodec_alloc_context3(cs->video_decoder); + + if (!cs->video_decoder_ctx) { + printf("init video_decoder_ctx failed\n"); + return 0; + } + + if (avcodec_open2(cs->video_decoder_ctx, cs->video_decoder, NULL) < 0) { + printf("opening video decoder failed\n"); + return 0; + } + + printf("init video decoder successful\n"); + return 1; +} + +int init_send_video(codec_state *cs) +{ + cs->video_input_format = av_find_input_format(VIDEO_DRIVER); + + if (avformat_open_input(&cs->video_format_ctx, DEFAULT_WEBCAM, cs->video_input_format, NULL) != 0) { + printf("opening video_input_format failed\n"); + return 0; + } + + avformat_find_stream_info(cs->video_format_ctx, NULL); + av_dump_format(cs->video_format_ctx, 0, DEFAULT_WEBCAM, 0); + + int i; + + for (i = 0; i < cs->video_format_ctx->nb_streams; ++i) { + if (cs->video_format_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { + cs->video_stream = i; + break; + } + } + + cs->webcam_decoder_ctx = cs->video_format_ctx->streams[cs->video_stream]->codec; + cs->webcam_decoder = avcodec_find_decoder(cs->webcam_decoder_ctx->codec_id); + + if (cs->webcam_decoder == NULL) { + printf("Unsupported codec\n"); + return 0; + } + + if (cs->webcam_decoder_ctx == NULL) { + printf("init webcam_decoder_ctx failed\n"); + return 0; + } + + if (avcodec_open2(cs->webcam_decoder_ctx, cs->webcam_decoder, NULL) < 0) { + printf("opening webcam decoder failed\n"); + return 0; + } + + cs->video_encoder = avcodec_find_encoder(VIDEO_CODEC); + + if (!cs->video_encoder) { + printf("init video_encoder failed\n"); + return 0; + } + + cs->video_encoder_ctx = avcodec_alloc_context3(cs->video_encoder); + + if (!cs->video_encoder_ctx) { + printf("init video_encoder_ctx failed\n"); + return 0; + } + + cs->video_encoder_ctx->bit_rate = VIDEO_BITRATE; + cs->video_encoder_ctx->rc_min_rate = cs->video_encoder_ctx->rc_max_rate = cs->video_encoder_ctx->bit_rate; + av_opt_set_double(cs->video_encoder_ctx->priv_data, "max-intra-rate", 90, 0); + av_opt_set(cs->video_encoder_ctx->priv_data, "quality", "realtime", 0); + + cs->video_encoder_ctx->thread_count = 4; + cs->video_encoder_ctx->rc_buffer_aggressivity = 0.95; + cs->video_encoder_ctx->rc_buffer_size = VIDEO_BITRATE * 6; + cs->video_encoder_ctx->profile = 3; + cs->video_encoder_ctx->qmax = 54; + cs->video_encoder_ctx->qmin = 4; + AVRational myrational = {1, 25}; + cs->video_encoder_ctx->time_base = myrational; + cs->video_encoder_ctx->gop_size = 99999; + cs->video_encoder_ctx->pix_fmt = PIX_FMT_YUV420P; + cs->video_encoder_ctx->width = cs->webcam_decoder_ctx->width; + cs->video_encoder_ctx->height = cs->webcam_decoder_ctx->height; + + if (avcodec_open2(cs->video_encoder_ctx, cs->video_encoder, NULL) < 0) { + printf("opening video encoder failed\n"); + return 0; + } + + printf("init video encoder successful\n"); + return 1; +} + +int init_send_audio(codec_state *cs) +{ + cs->support_send_audio = 0; + + const ALchar *pDeviceList = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER); + int i = 0; + const ALchar *device_names[20]; + + if (pDeviceList) { + printf("\nAvailable Capture Devices are:\n"); + + while (*pDeviceList) { + device_names[i] = pDeviceList; + printf("%d) %s\n", i, device_names[i]); + pDeviceList += strlen(pDeviceList) + 1; + ++i; + } + } + + printf("enter capture device number: \n"); + char dev[2]; + fgets(dev, sizeof(dev), stdin); + cs->audio_capture_device = alcCaptureOpenDevice(device_names[dev[0] - 48], AUDIO_SAMPLE_RATE, AL_FORMAT_MONO16, + AUDIO_FRAME_SIZE * 4); + + if (alcGetError(cs->audio_capture_device) != AL_NO_ERROR) { + printf("could not start capture device! %d\n", alcGetError(cs->audio_capture_device)); + return 0; + } + + int err = OPUS_OK; + cs->audio_bitrate = AUDIO_BITRATE; + cs->audio_encoder = opus_encoder_create(AUDIO_SAMPLE_RATE, 1, OPUS_APPLICATION_VOIP, &err); + err = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_BITRATE(cs->audio_bitrate)); + err = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_COMPLEXITY(10)); + err = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE)); + + opus_encoder_init(cs->audio_encoder, AUDIO_SAMPLE_RATE, 1, OPUS_APPLICATION_VOIP); + + int nfo; + err = opus_encoder_ctl(cs->audio_encoder, OPUS_GET_LOOKAHEAD(&nfo)); + /* printf("Encoder lookahead delay : %d\n", nfo); */ + printf("init audio encoder successful\n"); + + return 1; +} + +int init_encoder(codec_state *cs) +{ + avdevice_register_all(); + avcodec_register_all(); + avdevice_register_all(); + av_register_all(); + + pthread_mutex_init(&cs->rtp_msg_mutex_lock, NULL); + pthread_mutex_init(&cs->avcodec_mutex_lock, NULL); + + cs->support_send_video = init_send_video(cs); + cs->support_send_audio = init_send_audio(cs); + + cs->send_audio = 1; + cs->send_video = 1; + + return 1; +} + +int init_decoder(codec_state *cs) +{ + avdevice_register_all(); + avcodec_register_all(); + avdevice_register_all(); + av_register_all(); + + cs->receive_video = 0; + cs->receive_audio = 0; + + cs->support_receive_video = init_receive_video(cs); + cs->support_receive_audio = init_receive_audio(cs); + + cs->receive_audio = 1; + cs->receive_video = 1; + + return 1; +} + +int video_encoder_refresh(codec_state *cs, int bps) +{ + if (cs->video_encoder_ctx) + avcodec_close(cs->video_encoder_ctx); + + cs->video_encoder = avcodec_find_encoder(VIDEO_CODEC); + + if (!cs->video_encoder) { + printf("init video_encoder failed\n"); + return -1; + } + + cs->video_encoder_ctx = avcodec_alloc_context3(cs->video_encoder); + + if (!cs->video_encoder_ctx) { + printf("init video_encoder_ctx failed\n"); + return -1; + } + + cs->video_encoder_ctx->bit_rate = bps; + cs->video_encoder_ctx->rc_min_rate = cs->video_encoder_ctx->rc_max_rate = cs->video_encoder_ctx->bit_rate; + av_opt_set_double(cs->video_encoder_ctx->priv_data, "max-intra-rate", 90, 0); + av_opt_set(cs->video_encoder_ctx->priv_data, "quality", "realtime", 0); + + cs->video_encoder_ctx->thread_count = 4; + cs->video_encoder_ctx->rc_buffer_aggressivity = 0.95; + cs->video_encoder_ctx->rc_buffer_size = bps * 6; + cs->video_encoder_ctx->profile = 0; + cs->video_encoder_ctx->qmax = 54; + cs->video_encoder_ctx->qmin = 4; + AVRational myrational = {1, 25}; + cs->video_encoder_ctx->time_base = myrational; + cs->video_encoder_ctx->gop_size = 99999; + cs->video_encoder_ctx->pix_fmt = PIX_FMT_YUV420P; + cs->video_encoder_ctx->width = cs->webcam_decoder_ctx->width; + cs->video_encoder_ctx->height = cs->webcam_decoder_ctx->height; + + if (avcodec_open2(cs->video_encoder_ctx, cs->video_encoder, NULL) < 0) { + printf("opening video encoder failed\n"); + return -1; + } + return 0; +} + +void *encode_video_thread(void *arg) +{ + codec_state *cs = (codec_state *)arg; + AVPacket pkt1, *packet = &pkt1; + int p = 0; + int err; + int got_packet; + rtp_msg_t *s_video_msg; + int video_frame_finished; + AVFrame *s_video_frame; + AVFrame *webcam_frame; + s_video_frame = avcodec_alloc_frame(); + webcam_frame = avcodec_alloc_frame(); + AVPacket enc_video_packet; + + uint8_t *buffer; + int numBytes; + /* Determine required buffer size and allocate buffer */ + numBytes = avpicture_get_size(PIX_FMT_YUV420P, cs->webcam_decoder_ctx->width, cs->webcam_decoder_ctx->height); + buffer = (uint8_t *)av_calloc(numBytes * sizeof(uint8_t),1); + avpicture_fill((AVPicture *)s_video_frame, buffer, PIX_FMT_YUV420P, cs->webcam_decoder_ctx->width, + cs->webcam_decoder_ctx->height); + cs->sws_ctx = sws_getContext(cs->webcam_decoder_ctx->width, cs->webcam_decoder_ctx->height, + cs->webcam_decoder_ctx->pix_fmt, cs->webcam_decoder_ctx->width, cs->webcam_decoder_ctx->height, PIX_FMT_YUV420P, + SWS_BILINEAR, NULL, NULL, NULL); + + while (!cs->quit && cs->send_video) { + + if (av_read_frame(cs->video_format_ctx, packet) < 0) { + printf("error reading frame\n"); + + if (cs->video_format_ctx->pb->error != 0) + break; + + continue; + } + + if (packet->stream_index == cs->video_stream) { + if (avcodec_decode_video2(cs->webcam_decoder_ctx, webcam_frame, &video_frame_finished, packet) < 0) { + printf("couldn't decode\n"); + continue; + } + + av_free_packet(packet); + sws_scale(cs->sws_ctx, (uint8_t const * const *)webcam_frame->data, webcam_frame->linesize, 0, + cs->webcam_decoder_ctx->height, s_video_frame->data, s_video_frame->linesize); + /* create a new I-frame every 60 frames */ + ++p; + + if (p == 60) { + + s_video_frame->pict_type = AV_PICTURE_TYPE_BI ; + } else if (p == 61) { + s_video_frame->pict_type = AV_PICTURE_TYPE_I ; + p = 0; + } else { + s_video_frame->pict_type = AV_PICTURE_TYPE_P ; + } + + if (video_frame_finished) { + err = avcodec_encode_video2(cs->video_encoder_ctx, &enc_video_packet, s_video_frame, &got_packet); + + if (err < 0) { + printf("could not encode video frame\n"); + continue; + } + + if (!got_packet) { + continue; + } + + pthread_mutex_lock(&cs->rtp_msg_mutex_lock); + THREADLOCK() + + if (!enc_video_packet.data) fprintf(stderr, "video packet data is NULL\n"); + + s_video_msg = rtp_msg_new ( cs->_rtp_video, enc_video_packet.data, enc_video_packet.size ) ; + + if (!s_video_msg) { + printf("invalid message\n"); + } + + rtp_send_msg ( cs->_rtp_video, s_video_msg, cs->_networking ); + THREADUNLOCK() + pthread_mutex_unlock(&cs->rtp_msg_mutex_lock); + av_free_packet(&enc_video_packet); + } + } else { + av_free_packet(packet); + } + } + + /* clean up codecs */ + pthread_mutex_lock(&cs->avcodec_mutex_lock); + av_free(buffer); + av_free(webcam_frame); + av_free(s_video_frame); + sws_freeContext(cs->sws_ctx); + avcodec_close(cs->webcam_decoder_ctx); + avcodec_close(cs->video_encoder_ctx); + pthread_mutex_unlock(&cs->avcodec_mutex_lock); + pthread_exit ( NULL ); +} + +void *encode_audio_thread(void *arg) +{ + codec_state *cs = (codec_state *)arg; + rtp_msg_t *s_audio_msg; + unsigned char encoded_data[4096]; + int encoded_size = 0; + int16_t frame[4096]; + int frame_size = AUDIO_FRAME_SIZE; + ALint sample = 0; + alcCaptureStart(cs->audio_capture_device); + + while (!cs->quit && cs->send_audio) { + alcGetIntegerv(cs->audio_capture_device, ALC_CAPTURE_SAMPLES, (ALCsizei)sizeof(ALint), &sample); + + if (sample >= frame_size) { + alcCaptureSamples(cs->audio_capture_device, frame, frame_size); + encoded_size = opus_encode(cs->audio_encoder, frame, frame_size, encoded_data, 480); + + if (encoded_size <= 0) { + printf("Could not encode audio packet\n"); + } else { + pthread_mutex_lock(&cs->rtp_msg_mutex_lock); + THREADLOCK() + rtp_set_payload_type(cs->_rtp_audio, 96); + s_audio_msg = rtp_msg_new (cs->_rtp_audio, encoded_data, encoded_size) ; + rtp_send_msg ( cs->_rtp_audio, s_audio_msg, cs->_networking ); + pthread_mutex_unlock(&cs->rtp_msg_mutex_lock); + THREADUNLOCK() + } + } else { + usleep(1000); + } + } + + /* clean up codecs */ + pthread_mutex_lock(&cs->avcodec_mutex_lock); + alcCaptureStop(cs->audio_capture_device); + alcCaptureCloseDevice(cs->audio_capture_device); + + pthread_mutex_unlock(&cs->avcodec_mutex_lock); + pthread_exit ( NULL ); +} + + +int video_decoder_refresh(codec_state *cs, int width, int height) +{ + printf("need to refresh\n"); + screen = SDL_SetVideoMode(width, height, 0, 0); + + if (cs->video_picture.bmp) + SDL_FreeYUVOverlay(cs->video_picture.bmp); + + cs->video_picture.bmp = SDL_CreateYUVOverlay(width, height, SDL_YV12_OVERLAY, screen); + cs->sws_SDL_r_ctx = sws_getContext(width, height, cs->video_decoder_ctx->pix_fmt, width, height, PIX_FMT_YUV420P, + SWS_BILINEAR, NULL, NULL, NULL); + return 1; +} + +void *decode_video_thread(void *arg) +{ + codec_state *cs = (codec_state *)arg; + cs->video_stream = 0; + rtp_msg_t *r_msg; + int dec_frame_finished; + AVFrame *r_video_frame; + r_video_frame = avcodec_alloc_frame(); + AVPacket dec_video_packet; + av_new_packet (&dec_video_packet, 65536); + int width = 0; + int height = 0; + + while (!cs->quit && cs->receive_video) { + r_msg = rtp_recv_msg ( cs->_rtp_video ); + + if (r_msg) { + memcpy(dec_video_packet.data, r_msg->_data, r_msg->_length); + dec_video_packet.size = r_msg->_length; + avcodec_decode_video2(cs->video_decoder_ctx, r_video_frame, &dec_frame_finished, &dec_video_packet); + + if (dec_frame_finished) { + if (cs->video_decoder_ctx->width != width || cs->video_decoder_ctx->height != height) { + width = cs->video_decoder_ctx->width; + height = cs->video_decoder_ctx->height; + printf("w: %d h%d \n", width, height); + video_decoder_refresh(cs, width, height); + } + + display_received_frame(cs, r_video_frame); + } else { + /* TODO: request the sender to create a new i-frame immediatly */ + printf("bad video packet\n"); + } + + rtp_free_msg(cs->_rtp_video, r_msg); + } + + usleep(1000); + } + + printf("vend\n"); + /* clean up codecs */ + pthread_mutex_lock(&cs->avcodec_mutex_lock); + av_free(r_video_frame); + avcodec_close(cs->video_decoder_ctx); + pthread_mutex_unlock(&cs->avcodec_mutex_lock); + pthread_exit ( NULL ); +} + +void *decode_audio_thread(void *arg) +{ + codec_state *cs = (codec_state *)arg; + rtp_msg_t *r_msg; + + int frame_size = AUDIO_FRAME_SIZE; + int data_size; + + ALCdevice *dev; + ALCcontext *ctx; + ALuint source, *buffers; + dev = alcOpenDevice(NULL); + ctx = alcCreateContext(dev, NULL); + alcMakeContextCurrent(ctx); + int openal_buffers = 5; + + buffers = calloc(sizeof(ALuint) * openal_buffers,1); + alGenBuffers(openal_buffers, buffers); + alGenSources((ALuint)1, &source); + alSourcei(source, AL_LOOPING, AL_FALSE); + + ALuint buffer; + ALint val; + + ALenum error; + uint16_t zeros[frame_size]; + int i; + + for (i = 0; i < frame_size; i++) { + zeros[i] = 0; + } + + for (i = 0; i < openal_buffers; ++i) { + alBufferData(buffers[i], AL_FORMAT_MONO16, zeros, frame_size, 48000); + } + + alSourceQueueBuffers(source, openal_buffers, buffers); + alSourcePlay(source); + + if (alGetError() != AL_NO_ERROR) { + fprintf(stderr, "Error starting audio\n"); + cs->quit = 1; + } + + struct jitter_buffer *j_buf = NULL; + + j_buf = create_queue(20); + + int success = 0; + + int dec_frame_len; + + opus_int16 PCM[frame_size]; + + while (!cs->quit && cs->receive_audio) { + THREADLOCK() + r_msg = rtp_recv_msg ( cs->_rtp_audio ); + + if (r_msg) { + /* push the packet into the queue */ + queue(j_buf, r_msg); + } + + /* grab a packet from the queue */ + success = 0; + alGetSourcei(source, AL_BUFFERS_PROCESSED, &val); + + if (val > 0) + r_msg = dequeue(j_buf, &success); + + if (success > 0) { + /* good packet */ + if (success == 1) { + dec_frame_len = opus_decode(cs->audio_decoder, r_msg->_data, r_msg->_length, PCM, frame_size, 0); + rtp_free_msg(cs->_rtp_audio, r_msg); + } + + /* lost packet */ + if (success == 2) { + printf("lost packet\n"); + dec_frame_len = opus_decode(cs->audio_decoder, NULL, 0, PCM, frame_size, 1); + } + + if (dec_frame_len > 0) { + alGetSourcei(source, AL_BUFFERS_PROCESSED, &val); + + if (val <= 0) + continue; + + alSourceUnqueueBuffers(source, 1, &buffer); + data_size = av_samples_get_buffer_size(NULL, 1, dec_frame_len, AV_SAMPLE_FMT_S16, 1); + alBufferData(buffer, AL_FORMAT_MONO16, PCM, data_size, 48000); + int error = alGetError(); + + if (error != AL_NO_ERROR) { + fprintf(stderr, "Error setting buffer %d\n", error); + break; + } + + alSourceQueueBuffers(source, 1, &buffer); + + if (alGetError() != AL_NO_ERROR) { + fprintf(stderr, "error: could not buffer audio\n"); + break; + } + + alGetSourcei(source, AL_SOURCE_STATE, &val); + + if (val != AL_PLAYING) + alSourcePlay(source); + + + } + } + + THREADUNLOCK() + usleep(1000); + } + + /* clean up codecs */ + pthread_mutex_lock(&cs->avcodec_mutex_lock); + + /* clean up openal */ + alDeleteSources(1, &source); + alDeleteBuffers(openal_buffers, buffers); + alcMakeContextCurrent(NULL); + alcDestroyContext(ctx); + alcCloseDevice(dev); + pthread_mutex_unlock(&cs->avcodec_mutex_lock); + pthread_exit ( NULL ); +} diff --git a/toxmsi/toxmedia.h b/toxmsi/toxmedia.h new file mode 100644 index 00000000..7eea39ae --- /dev/null +++ b/toxmsi/toxmedia.h @@ -0,0 +1,168 @@ +/* AV_codec.h + * + * Audio and video codec intitialisation, encoding/decoding and playback + * + * Copyright (C) 2013 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ + +/*----------------------------------------------------------------------------------*/ +#ifndef _AVCODEC_H_ +#define _AVCODEC_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "toxrtp.h" +#include "tox.h" + +#include +#include + +/* ffmpeg VP8 codec ID */ +#define VIDEO_CODEC AV_CODEC_ID_VP8 + +/* ffmpeg Opus codec ID */ +#define AUDIO_CODEC AV_CODEC_ID_OPUS + +/* default video bitrate in bytes/s */ +#define VIDEO_BITRATE 10*1000 + +/* default audio bitrate in bytes/s */ +#define AUDIO_BITRATE 64000 + +/* audio frame duration in miliseconds */ +#define AUDIO_FRAME_DURATION 20 + +/* audio sample rate recommended to be 48kHz for Opus */ +#define AUDIO_SAMPLE_RATE 48000 + +/* the amount of samples in one audio frame */ +#define AUDIO_FRAME_SIZE AUDIO_SAMPLE_RATE*AUDIO_FRAME_DURATION/1000 + +/* the quit event for SDL */ +#define FF_QUIT_EVENT (SDL_USEREVENT + 2) + +#ifdef __linux__ +#define VIDEO_DRIVER "video4linux2" +#define DEFAULT_WEBCAM "/dev/video0" +#endif + +#ifdef WIN32 +#define VIDEO_DRIVER "vfwcap" +#define DEFAULT_WEBCAM "0" +#endif + +extern SDL_Surface *screen; + +typedef struct { + SDL_Overlay *bmp; + int width, height; +} VideoPicture; + + +typedef struct { + uint8_t send_audio; + uint8_t receive_audio; + uint8_t send_video; + uint8_t receive_video; + + uint8_t support_send_audio; + uint8_t support_send_video; + uint8_t support_receive_audio; + uint8_t support_receive_video; + + /* video encoding */ + AVInputFormat *video_input_format; + AVFormatContext *video_format_ctx; + uint8_t video_stream; + AVCodecContext *webcam_decoder_ctx; + AVCodec *webcam_decoder; + AVCodecContext *video_encoder_ctx; + AVCodec *video_encoder; + + /* video decoding */ + AVCodecContext *video_decoder_ctx; + AVCodec *video_decoder; + + /* audio encoding */ + ALCdevice *audio_capture_device; + OpusEncoder *audio_encoder; + int audio_bitrate; + + /* audio decoding */ + OpusDecoder *audio_decoder; + + uint8_t req_video_refresh; + + /* context for converting image format to something SDL can use*/ + struct SwsContext *sws_SDL_r_ctx; + + /* context for converting webcam image format to something the video encoder can use */ + struct SwsContext *sws_ctx; + + /* rendered video picture, ready for display */ + VideoPicture video_picture; + + rtp_session_t *_rtp_video; + rtp_session_t *_rtp_audio; + int socket; + Networking_Core *_networking; + + pthread_t encode_audio_thread; + pthread_t encode_video_thread; + + pthread_t decode_audio_thread; + pthread_t decode_video_thread; + + pthread_mutex_t rtp_msg_mutex_lock; + pthread_mutex_t avcodec_mutex_lock; + + uint8_t quit; + SDL_Event SDL_event; + + msi_session_t *_msi; + uint32_t _frame_rate; + uint16_t _send_port, _recv_port; + int _tox_sock; + //pthread_id _medialoop_id; + +} codec_state; + +int display_received_frame(codec_state *cs, AVFrame *r_video_frame); +int init_receive_audio(codec_state *cs); +int init_decoder(codec_state *cs); +int init_send_video(codec_state *cs); +int init_send_audio(codec_state *cs); +int init_encoder(codec_state *cs); +int video_encoder_refresh(codec_state *cs, int bps); +void *encode_video_thread(void *arg); +void *encode_audio_thread(void *arg); +int video_decoder_refresh(codec_state *cs, int width, int height); +int handle_rtp_video_packet(codec_state *cs, rtp_msg_t *r_msg); +void *decode_video_thread(void *arg); +void *decode_audio_thread(void *arg); + +#endif -- cgit v1.2.3