diff --git a/.cirrus.yml b/.cirrus.yml index 65d6554f70..fdb7df7368 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -7,10 +7,11 @@ cirrus-ci_task: configure_script: - /src/workspace/tools/inject-repo c-toxcore test_all_script: - - bazel test -k + - TEST="bazel test -k --build_tag_filters=-haskell --test_tag_filters=-haskell --remote_download_minimal --config=ci --config=release - //c-toxcore/... + //c-toxcore/..." + - $TEST || $TEST || $TEST || $TEST diff --git a/.restyled.yaml b/.restyled.yaml index f0060d757a..5ca9b51cef 100644 --- a/.restyled.yaml +++ b/.restyled.yaml @@ -1,4 +1,7 @@ --- +exclude: + - "**/*.api.h" + restylers: - astyle: arguments: ["--options=other/astyle/astylerc"] diff --git a/CMakeLists.txt b/CMakeLists.txt index 51e1e99f48..26e4761c43 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -268,6 +268,7 @@ if(BUILD_TOXAV) toxav/rtp.h toxav/toxav.c toxav/toxav.h + toxav/toxav_hacks.h toxav/toxav_old.c toxav/video.c toxav/video.h) diff --git a/other/analysis/run-clang b/other/analysis/run-clang index fbb0d427fc..939aff7b9a 100755 --- a/other/analysis/run-clang +++ b/other/analysis/run-clang @@ -3,23 +3,24 @@ . other/analysis/gen-file.sh echo "Running Clang compiler" -clang++ -o /dev/null amalgamation.cc \ - $CPPFLAGS \ - $LDFLAGS \ - -std=c++11 \ - -Werror \ - -Weverything \ - -Wno-c++98-compat-pedantic \ - -Wno-c99-extensions \ - -Wno-cast-align \ - -Wno-conversion \ - -Wno-covered-switch-default \ - -Wno-disabled-macro-expansion \ - -Wno-documentation-deprecated-sync \ - -Wno-missing-field-initializers \ - -Wno-old-style-cast \ - -Wno-padded \ - -Wno-sign-compare \ - -Wno-unreachable-code-return \ - -Wno-unused-parameter \ - -Wno-used-but-marked-unused \ +clang++ -o /dev/null amalgamation.cc \ + "$CPPFLAGS" \ + "$LDFLAGS" \ + -std=c++11 \ + -Werror \ + -Weverything \ + -Wno-c++98-compat-pedantic \ + -Wno-c99-extensions \ + -Wno-cast-align \ + -Wno-conversion \ + -Wno-covered-switch-default \ + -Wno-disabled-macro-expansion \ + -Wno-documentation-deprecated-sync \ + -Wno-missing-field-initializers \ + -Wno-old-style-cast \ + -Wno-padded \ + -Wno-sign-compare \ + -Wno-unreachable-code-return \ + -Wno-unused-parameter \ + -Wno-used-but-marked-unused \ + -fdiagnostics-color=always diff --git a/toxav/BUILD.bazel b/toxav/BUILD.bazel index d7e6b6e9c4..24dc841911 100644 --- a/toxav/BUILD.bazel +++ b/toxav/BUILD.bazel @@ -29,99 +29,46 @@ cc_test( ], ) -cc_library( - name = "ring_buffer_srcs", - hdrs = [ - "ring_buffer.c", - "ring_buffer.h", - ], - visibility = ["//c-toxcore/testing:__pkg__"], - deps = ["//c-toxcore/toxcore:ccompat"], -) - -cc_library( - name = "bwcontroller", - srcs = ["bwcontroller.c"], - hdrs = ["bwcontroller.h"], - deps = [ - ":ring_buffer", - "//c-toxcore/toxcore", - "//c-toxcore/toxcore:Messenger", - ], -) - -cc_library( - name = "rtp", - srcs = ["rtp.c"], - hdrs = ["rtp.h"], - deps = [":bwcontroller"], -) - cc_test( name = "rtp_test", size = "small", srcs = ["rtp_test.cc"], deps = [ - ":rtp", + ":toxav", "//c-toxcore/toxcore:crypto_core", "@com_google_googletest//:gtest_main", ], ) -cc_library( - name = "audio", - srcs = ["audio.c"], - hdrs = ["audio.h"], - deps = [ - ":public", - ":rtp", - "//c-toxcore/toxcore:network", - "@opus", - ], -) - -cc_library( - name = "video", - srcs = [ - "msi.c", - "video.c", - ], - hdrs = [ - "msi.h", - "video.h", - ], - deps = [ - ":audio", - ":public", - "//c-toxcore/toxcore:network", - "@libvpx", - ], -) - -cc_library( - name = "groupav", - srcs = ["groupav.c"], - hdrs = ["groupav.h"], - deps = [ - "//c-toxcore/toxcore", - "@opus", - ], -) - cc_library( name = "toxav", srcs = [ + "audio.c", + "bwcontroller.c", + "groupav.c", + "msi.c", + "rtp.c", "toxav.c", "toxav_old.c", + "video.c", ], hdrs = [ + "audio.h", + "bwcontroller.h", + "groupav.h", + "msi.h", + "rtp.h", "toxav.api.h", "toxav.h", + "toxav_hacks.h", + "video.h", ], visibility = ["//c-toxcore:__subpackages__"], deps = [ - ":groupav", - ":video", + ":ring_buffer", + "//c-toxcore/toxcore", + "@libvpx", + "@opus", ], ) diff --git a/toxav/Makefile.inc b/toxav/Makefile.inc index 7b7881985c..fd7b56d77f 100644 --- a/toxav/Makefile.inc +++ b/toxav/Makefile.inc @@ -19,6 +19,7 @@ libtoxav_la_SOURCES = ../toxav/rtp.h \ ../toxav/ring_buffer.h \ ../toxav/ring_buffer.c \ ../toxav/toxav.h \ + ../toxav/toxav_hacks.h \ ../toxav/toxav.c \ ../toxav/toxav_old.c diff --git a/toxav/audio.c b/toxav/audio.c index cf9097d7e9..420a005670 100644 --- a/toxav/audio.c +++ b/toxav/audio.c @@ -15,32 +15,33 @@ #include "../toxcore/logger.h" #include "../toxcore/mono_time.h" +#include "../toxcore/network.h" static struct JitterBuffer *jbuf_new(uint32_t capacity); static void jbuf_clear(struct JitterBuffer *q); static void jbuf_free(struct JitterBuffer *q); -static int jbuf_write(const Logger *log, struct JitterBuffer *q, struct RTPMessage *m); +static int jbuf_write(Tox *tox, struct JitterBuffer *q, struct RTPMessage *m); static struct RTPMessage *jbuf_read(struct JitterBuffer *q, int32_t *success); -static OpusEncoder *create_audio_encoder(const Logger *log, int32_t bit_rate, int32_t sampling_rate, +static OpusEncoder *create_audio_encoder(Tox *tox, int32_t bit_rate, int32_t sampling_rate, int32_t channel_count); -static bool reconfigure_audio_encoder(const Logger *log, OpusEncoder **e, int32_t new_br, int32_t new_sr, +static bool reconfigure_audio_encoder(Tox *tox, OpusEncoder **e, int32_t new_br, int32_t new_sr, uint8_t new_ch, int32_t *old_br, int32_t *old_sr, int32_t *old_ch); -static bool reconfigure_audio_decoder(ACSession *ac, int32_t sampling_rate, int8_t channels); +static bool reconfigure_audio_decoder(ACSession *ac, Tox *tox, int32_t sampling_rate, int8_t channels); -ACSession *ac_new(Mono_Time *mono_time, const Logger *log, ToxAV *av, uint32_t friend_number, +ACSession *ac_new(Mono_Time *mono_time, Tox *tox, ToxAV *av, uint32_t friend_number, toxav_audio_receive_frame_cb *cb, void *cb_data) { ACSession *ac = (ACSession *)calloc(sizeof(ACSession), 1); if (!ac) { - LOGGER_WARNING(log, "Allocation failed! Application might misbehave!"); + LOGGER_API_WARNING(tox, "Allocation failed! Application might misbehave!"); return nullptr; } if (create_recursive_mutex(ac->queue_mutex) != 0) { - LOGGER_WARNING(log, "Failed to create recursive mutex!"); + LOGGER_API_WARNING(tox, "Failed to create recursive mutex!"); free(ac); return nullptr; } @@ -49,23 +50,22 @@ ACSession *ac_new(Mono_Time *mono_time, const Logger *log, ToxAV *av, uint32_t f ac->decoder = opus_decoder_create(AUDIO_DECODER_START_SAMPLE_RATE, AUDIO_DECODER_START_CHANNEL_COUNT, &status); if (status != OPUS_OK) { - LOGGER_ERROR(log, "Error while starting audio decoder: %s", opus_strerror(status)); + LOGGER_API_ERROR(tox, "Error while starting audio decoder: %s", opus_strerror(status)); goto BASE_CLEANUP; } ac->j_buf = jbuf_new(AUDIO_JITTERBUFFER_COUNT); if (ac->j_buf == nullptr) { - LOGGER_WARNING(log, "Jitter buffer creaton failed!"); + LOGGER_API_WARNING(tox, "Jitter buffer creaton failed!"); opus_decoder_destroy(ac->decoder); goto BASE_CLEANUP; } ac->mono_time = mono_time; - ac->log = log; /* Initialize encoders with default values */ - ac->encoder = create_audio_encoder(log, AUDIO_START_BITRATE, AUDIO_START_SAMPLE_RATE, AUDIO_START_CHANNEL_COUNT); + ac->encoder = create_audio_encoder(tox, AUDIO_START_BITRATE, AUDIO_START_SAMPLE_RATE, AUDIO_START_CHANNEL_COUNT); if (ac->encoder == nullptr) { goto DECODER_CLEANUP; @@ -113,7 +113,7 @@ void ac_kill(ACSession *ac) pthread_mutex_destroy(ac->queue_mutex); - LOGGER_DEBUG(ac->log, "Terminated audio handler: %p", (void *)ac); + LOGGER_API_DEBUG(ac->tox, "Terminated audio handler: %p", (void *)ac); free(ac); } @@ -138,7 +138,7 @@ void ac_iterate(ACSession *ac) pthread_mutex_unlock(ac->queue_mutex); if (rc == 2) { - LOGGER_DEBUG(ac->log, "OPUS correction"); + LOGGER_API_DEBUG(ac->tox, "OPUS correction"); int fs = (ac->lp_sampling_rate * ac->lp_frame_duration) / 1000; rc = opus_decode(ac->decoder, nullptr, 0, temp_audio_buffer, fs, 1); } else { @@ -150,7 +150,7 @@ void ac_iterate(ACSession *ac) if (rc != -1) { cs->last_packet_sampling_rate = rc; } else { - LOGGER_WARNING(ac->log, "Failed to load packet values!"); + LOGGER_API_WARNING(ac->tox, "Failed to load packet values!"); rtp_free_msg(msg); continue; } @@ -167,8 +167,8 @@ void ac_iterate(ACSession *ac) /** NOTE: even though OPUS supports decoding mono frames with stereo decoder and vice versa, * it didn't work quite well. */ - if (!reconfigure_audio_decoder(ac, ac->lp_sampling_rate, ac->lp_channel_count)) { - LOGGER_WARNING(ac->log, "Failed to reconfigure decoder!"); + if (!reconfigure_audio_decoder(ac, ac->tox, ac->lp_sampling_rate, ac->lp_channel_count)) { + LOGGER_API_WARNING(ac->tox, "Failed to reconfigure decoder!"); free(msg); continue; } @@ -187,7 +187,7 @@ void ac_iterate(ACSession *ac) } if (rc < 0) { - LOGGER_WARNING(ac->log, "Decoding error: %s", opus_strerror(rc)); + LOGGER_API_WARNING(ac->tox, "Decoding error: %s", opus_strerror(rc)); } else if (ac->acb) { ac->lp_frame_duration = (rc * 1000) / ac->lp_sampling_rate; @@ -214,23 +214,23 @@ int ac_queue_message(Mono_Time *mono_time, void *acp, struct RTPMessage *msg) ACSession *ac = (ACSession *)acp; if ((msg->header.pt & 0x7f) == (RTP_TYPE_AUDIO + 2) % 128) { - LOGGER_WARNING(ac->log, "Got dummy!"); + LOGGER_API_WARNING(ac->tox, "Got dummy!"); free(msg); return 0; } if ((msg->header.pt & 0x7f) != RTP_TYPE_AUDIO % 128) { - LOGGER_WARNING(ac->log, "Invalid payload type!"); + LOGGER_API_WARNING(ac->tox, "Invalid payload type!"); free(msg); return -1; } pthread_mutex_lock(ac->queue_mutex); - int rc = jbuf_write(ac->log, (struct JitterBuffer *)ac->j_buf, msg); + int rc = jbuf_write(ac->tox, (struct JitterBuffer *)ac->j_buf, msg); pthread_mutex_unlock(ac->queue_mutex); if (rc == -1) { - LOGGER_WARNING(ac->log, "Could not queue the message!"); + LOGGER_API_WARNING(ac->tox, "Could not queue the message!"); free(msg); return -1; } @@ -240,7 +240,7 @@ int ac_queue_message(Mono_Time *mono_time, void *acp, struct RTPMessage *msg) int ac_reconfigure_encoder(ACSession *ac, int32_t bit_rate, int32_t sampling_rate, uint8_t channels) { - if (!ac || !reconfigure_audio_encoder(ac->log, &ac->encoder, bit_rate, + if (!ac || !reconfigure_audio_encoder(ac->tox, &ac->encoder, bit_rate, sampling_rate, channels, &ac->le_bit_rate, &ac->le_sample_rate, @@ -286,6 +286,7 @@ static struct JitterBuffer *jbuf_new(uint32_t capacity) q->capacity = capacity; return q; } + static void jbuf_clear(struct JitterBuffer *q) { for (; q->bottom != q->top; ++q->bottom) { @@ -295,6 +296,7 @@ static void jbuf_clear(struct JitterBuffer *q) } } } + static void jbuf_free(struct JitterBuffer *q) { if (!q) { @@ -305,14 +307,19 @@ static void jbuf_free(struct JitterBuffer *q) free(q->queue); free(q); } -static int jbuf_write(const Logger *log, struct JitterBuffer *q, struct RTPMessage *m) + +/* + * if -1 is returned the RTPMessage m needs to be free'd by the caller + * if 0 is returned the RTPMessage m is stored in the ringbuffer and must NOT be freed by the caller + */ +static int jbuf_write(Tox *tox, struct JitterBuffer *q, struct RTPMessage *m) { uint16_t sequnum = m->header.sequnum; unsigned int num = sequnum % q->size; if ((uint32_t)(sequnum - q->bottom) > q->size) { - LOGGER_DEBUG(log, "Clearing filled jitter buffer: %p", (void *)q); + LOGGER_API_DEBUG(tox, "Clearing filled jitter buffer: %p", (void *)q); jbuf_clear(q); q->bottom = sequnum - q->capacity; @@ -333,6 +340,7 @@ static int jbuf_write(const Logger *log, struct JitterBuffer *q, struct RTPMessa return 0; } + static struct RTPMessage *jbuf_read(struct JitterBuffer *q, int32_t *success) { if (q->top == q->bottom) { @@ -359,7 +367,8 @@ static struct RTPMessage *jbuf_read(struct JitterBuffer *q, int32_t *success) *success = 0; return nullptr; } -static OpusEncoder *create_audio_encoder(const Logger *log, int32_t bit_rate, int32_t sampling_rate, + +static OpusEncoder *create_audio_encoder(Tox *tox, int32_t bit_rate, int32_t sampling_rate, int32_t channel_count) { int status = OPUS_OK; @@ -371,7 +380,7 @@ static OpusEncoder *create_audio_encoder(const Logger *log, int32_t bit_rate, in OpusEncoder *rc = opus_encoder_create(sampling_rate, channel_count, OPUS_APPLICATION_VOIP, &status); if (status != OPUS_OK) { - LOGGER_ERROR(log, "Error while starting audio encoder: %s", opus_strerror(status)); + LOGGER_API_ERROR(tox, "Error while starting audio encoder: %s", opus_strerror(status)); return nullptr; } @@ -388,7 +397,7 @@ static OpusEncoder *create_audio_encoder(const Logger *log, int32_t bit_rate, in status = opus_encoder_ctl(rc, OPUS_SET_BITRATE(bit_rate)); if (status != OPUS_OK) { - LOGGER_ERROR(log, "Error while setting encoder ctl: %s", opus_strerror(status)); + LOGGER_API_ERROR(tox, "Error while setting encoder ctl: %s", opus_strerror(status)); goto FAILURE; } @@ -404,7 +413,7 @@ static OpusEncoder *create_audio_encoder(const Logger *log, int32_t bit_rate, in status = opus_encoder_ctl(rc, OPUS_SET_INBAND_FEC(1)); if (status != OPUS_OK) { - LOGGER_ERROR(log, "Error while setting encoder ctl: %s", opus_strerror(status)); + LOGGER_API_ERROR(tox, "Error while setting encoder ctl: %s", opus_strerror(status)); goto FAILURE; } @@ -424,7 +433,7 @@ static OpusEncoder *create_audio_encoder(const Logger *log, int32_t bit_rate, in status = opus_encoder_ctl(rc, OPUS_SET_PACKET_LOSS_PERC(AUDIO_OPUS_PACKET_LOSS_PERC)); if (status != OPUS_OK) { - LOGGER_ERROR(log, "Error while setting encoder ctl: %s", opus_strerror(status)); + LOGGER_API_ERROR(tox, "Error while setting encoder ctl: %s", opus_strerror(status)); goto FAILURE; } @@ -442,7 +451,7 @@ static OpusEncoder *create_audio_encoder(const Logger *log, int32_t bit_rate, in status = opus_encoder_ctl(rc, OPUS_SET_COMPLEXITY(AUDIO_OPUS_COMPLEXITY)); if (status != OPUS_OK) { - LOGGER_ERROR(log, "Error while setting encoder ctl: %s", opus_strerror(status)); + LOGGER_API_ERROR(tox, "Error while setting encoder ctl: %s", opus_strerror(status)); goto FAILURE; } @@ -453,12 +462,12 @@ static OpusEncoder *create_audio_encoder(const Logger *log, int32_t bit_rate, in return nullptr; } -static bool reconfigure_audio_encoder(const Logger *log, OpusEncoder **e, int32_t new_br, int32_t new_sr, +static bool reconfigure_audio_encoder(Tox *tox, OpusEncoder **e, int32_t new_br, int32_t new_sr, uint8_t new_ch, int32_t *old_br, int32_t *old_sr, int32_t *old_ch) { /* Values are checked in toxav.c */ if (*old_sr != new_sr || *old_ch != new_ch) { - OpusEncoder *new_encoder = create_audio_encoder(log, new_br, new_sr, new_ch); + OpusEncoder *new_encoder = create_audio_encoder(tox, new_br, new_sr, new_ch); if (new_encoder == nullptr) { return false; @@ -473,7 +482,7 @@ static bool reconfigure_audio_encoder(const Logger *log, OpusEncoder **e, int32_ int status = opus_encoder_ctl(*e, OPUS_SET_BITRATE(new_br)); if (status != OPUS_OK) { - LOGGER_ERROR(log, "Error while setting encoder ctl: %s", opus_strerror(status)); + LOGGER_API_ERROR(tox, "Error while setting encoder ctl: %s", opus_strerror(status)); return false; } @@ -481,11 +490,11 @@ static bool reconfigure_audio_encoder(const Logger *log, OpusEncoder **e, int32_ *old_sr = new_sr; *old_ch = new_ch; - LOGGER_DEBUG(log, "Reconfigured audio encoder br: %d sr: %d cc:%d", new_br, new_sr, new_ch); + LOGGER_API_DEBUG(tox, "Reconfigured audio encoder br: %d sr: %d cc:%d", new_br, new_sr, new_ch); return true; } -static bool reconfigure_audio_decoder(ACSession *ac, int32_t sampling_rate, int8_t channels) +static bool reconfigure_audio_decoder(ACSession *ac, Tox *tox, int32_t sampling_rate, int8_t channels) { if (sampling_rate != ac->ld_sample_rate || channels != ac->ld_channel_count) { if (current_time_monotonic(ac->mono_time) - ac->ldrts < 500) { @@ -496,7 +505,7 @@ static bool reconfigure_audio_decoder(ACSession *ac, int32_t sampling_rate, int8 OpusDecoder *new_dec = opus_decoder_create(sampling_rate, channels, &status); if (status != OPUS_OK) { - LOGGER_ERROR(ac->log, "Error while starting audio decoder(%d %d): %s", sampling_rate, channels, opus_strerror(status)); + LOGGER_API_ERROR(tox, "Error while starting audio decoder(%d %d): %s", sampling_rate, channels, opus_strerror(status)); return false; } @@ -507,7 +516,7 @@ static bool reconfigure_audio_decoder(ACSession *ac, int32_t sampling_rate, int8 opus_decoder_destroy(ac->decoder); ac->decoder = new_dec; - LOGGER_DEBUG(ac->log, "Reconfigured audio decoder sr: %d cc: %d", sampling_rate, channels); + LOGGER_API_DEBUG(tox, "Reconfigured audio decoder sr: %d cc: %d", sampling_rate, channels); } return true; diff --git a/toxav/audio.h b/toxav/audio.h index 6d609ee7e0..1a53228956 100644 --- a/toxav/audio.h +++ b/toxav/audio.h @@ -34,9 +34,13 @@ #define AUDIO_MAX_BUFFER_SIZE_PCM16 ((AUDIO_MAX_SAMPLE_RATE * AUDIO_MAX_FRAME_DURATION_MS) / 1000) #define AUDIO_MAX_BUFFER_SIZE_BYTES (AUDIO_MAX_BUFFER_SIZE_PCM16 * 2) +#ifndef TOX_DEFINED +#define TOX_DEFINED +typedef struct Tox Tox; +#endif /* TOX_DEFINED */ + typedef struct ACSession_s { Mono_Time *mono_time; - const Logger *log; /* encoding */ OpusEncoder *encoder; @@ -61,9 +65,10 @@ typedef struct ACSession_s { /* Audio frame receive callback */ toxav_audio_receive_frame_cb *acb; void *acb_user_data; + Tox *tox; } ACSession; -ACSession *ac_new(Mono_Time *mono_time, const Logger *log, ToxAV *av, uint32_t friend_number, +ACSession *ac_new(Mono_Time *mono_time, Tox *tox, ToxAV *av, uint32_t friend_number, toxav_audio_receive_frame_cb *cb, void *cb_data); void ac_kill(ACSession *ac); void ac_iterate(ACSession *ac); diff --git a/toxav/bwcontroller.c b/toxav/bwcontroller.c index 6f3f4d005f..46f7cdea08 100644 --- a/toxav/bwcontroller.c +++ b/toxav/bwcontroller.c @@ -7,6 +7,7 @@ #endif /* HAVE_CONFIG_H */ #include "bwcontroller.h" +#include "toxav_hacks.h" #include #include @@ -17,8 +18,11 @@ #include "../toxcore/logger.h" #include "../toxcore/mono_time.h" +#include "../toxcore/network.h" +#include "../toxcore/tox_private.h" #include "../toxcore/util.h" + #define BWC_PACKET_ID 196 #define BWC_SEND_INTERVAL_MS 950 // 0.95s #define BWC_AVG_PKT_COUNT 20 @@ -41,8 +45,6 @@ typedef struct BWCRcvPkt { struct BWController_s { m_cb *mcb; void *mcb_user_data; - - Messenger *m; Tox *tox; uint32_t friend_number; @@ -52,6 +54,7 @@ struct BWController_s { uint32_t packet_loss_counted_cycles; Mono_Time *bwc_mono_time; + bool bwc_receive_active; }; struct BWCMessage { @@ -59,24 +62,24 @@ struct BWCMessage { uint32_t recv; }; -static int bwc_handle_data(Messenger *m, uint32_t friendnumber, const uint8_t *data, uint16_t length, void *object); static int bwc_send_custom_lossy_packet(Tox *tox, int32_t friendnumber, const uint8_t *data, uint32_t length); +static void bwc_handle_data(Tox *tox, uint32_t friendnumber, const uint8_t *data, size_t length, void *dummy); static void send_update(BWController *bwc); -BWController *bwc_new(Messenger *m, Tox *tox, uint32_t friendnumber, m_cb *mcb, void *mcb_user_data, - Mono_Time *bwc_mono_time) + +BWController *bwc_new(Tox *tox, uint32_t friendnumber, m_cb *mcb, void *mcb_user_data, Mono_Time *bwc_mono_time) { BWController *retu = (BWController *)calloc(sizeof(struct BWController_s), 1); - LOGGER_DEBUG(m->log, "Creating bandwidth controller"); + LOGGER_API_DEBUG(tox, "Creating bandwidth controller"); retu->mcb = mcb; retu->mcb_user_data = mcb_user_data; - retu->m = m; retu->friend_number = friendnumber; retu->bwc_mono_time = bwc_mono_time; uint64_t now = current_time_monotonic(bwc_mono_time); retu->cycle.last_sent_timestamp = now; retu->cycle.last_refresh_timestamp = now; retu->tox = tox; + retu->bwc_receive_active = true; /* default: true */ retu->rcvpkt.rb = rb_new(BWC_AVG_PKT_COUNT); retu->cycle.lost = 0; retu->cycle.recv = 0; @@ -87,7 +90,6 @@ BWController *bwc_new(Messenger *m, Tox *tox, uint32_t friendnumber, m_cb *mcb, rb_write(retu->rcvpkt.rb, &retu->rcvpkt.packet_length_array[i]); } - m_callback_rtp_packet(m, friendnumber, BWC_PACKET_ID, bwc_handle_data, retu); return retu; } @@ -97,7 +99,6 @@ void bwc_kill(BWController *bwc) return; } - m_callback_rtp_packet(bwc->m, bwc->friend_number, BWC_PACKET_ID, nullptr, nullptr); rb_kill(bwc->rcvpkt.rb); free(bwc); } @@ -109,7 +110,7 @@ void bwc_add_lost(BWController *bwc, uint32_t bytes_lost) } if (bytes_lost > 0) { - LOGGER_DEBUG(bwc->m->log, "BWC lost(1): %d", (int)bytes_lost); + LOGGER_API_DEBUG(bwc->tox, "BWC lost(1): %d", (int)bytes_lost); bwc->cycle.lost += bytes_lost; send_update(bwc); } @@ -133,9 +134,9 @@ static void send_update(BWController *bwc) bwc->packet_loss_counted_cycles = 0; if (bwc->cycle.lost) { - LOGGER_DEBUG(bwc->m->log, "%p Sent update rcv: %u lost: %u percent: %f %%", - (void *)bwc, bwc->cycle.recv, bwc->cycle.lost, - (((double) bwc->cycle.lost / (bwc->cycle.recv + bwc->cycle.lost)) * 100.0)); + LOGGER_API_DEBUG(bwc->tox, "%p Sent update rcv: %u lost: %u percent: %f %%", + (void *)bwc, bwc->cycle.recv, bwc->cycle.lost, + (((double) bwc->cycle.lost / (bwc->cycle.recv + bwc->cycle.lost)) * 100.0)); uint8_t bwc_packet[sizeof(struct BWCMessage) + 1]; size_t offset = 0; @@ -147,10 +148,7 @@ static void send_update(BWController *bwc) assert(offset == sizeof(bwc_packet)); if (bwc_send_custom_lossy_packet(bwc->tox, bwc->friend_number, bwc_packet, sizeof(bwc_packet)) == -1) { - const char *netstrerror = net_new_strerror(net_error()); - LOGGER_WARNING(bwc->m->log, "BWC send failed (len: %u)! std error: %s, net error %s", - (unsigned)sizeof(bwc_packet), strerror(errno), netstrerror); - net_kill_strerror(netstrerror); + LOGGER_API_WARNING(bwc->tox, "BWC send failed"); } } @@ -162,11 +160,11 @@ static void send_update(BWController *bwc) static int on_update(BWController *bwc, const struct BWCMessage *msg) { - LOGGER_DEBUG(bwc->m->log, "%p Got update from peer", (void *)bwc); + LOGGER_API_DEBUG(bwc->tox, "%p Got update from peer", (void *)bwc); /* Peers sent update too soon */ if (bwc->cycle.last_recv_timestamp + BWC_SEND_INTERVAL_MS > current_time_monotonic(bwc->bwc_mono_time)) { - LOGGER_INFO(bwc->m->log, "%p Rejecting extra update", (void *)bwc); + LOGGER_API_INFO(bwc->tox, "%p Rejecting extra update", (void *)bwc); return -1; } @@ -176,8 +174,8 @@ static int on_update(BWController *bwc, const struct BWCMessage *msg) const uint32_t lost = msg->lost; if (lost && bwc->mcb) { - LOGGER_DEBUG(bwc->m->log, "recved: %u lost: %u percentage: %f %%", recv, lost, - (((double) lost / (recv + lost)) * 100.0)); + LOGGER_API_DEBUG(bwc->tox, "recved: %u lost: %u percentage: %f %%", recv, lost, + (((double) lost / (recv + lost)) * 100.0)); bwc->mcb(bwc, bwc->friend_number, ((float) lost / (recv + lost)), bwc->mcb_user_data); @@ -186,6 +184,49 @@ static int on_update(BWController *bwc, const struct BWCMessage *msg) return 0; } +static void bwc_handle_data(Tox *tox, uint32_t friendnumber, const uint8_t *data, size_t length, void *dummy) +{ + if (length - 1 != sizeof(struct BWCMessage)) { + return; + } + + /* get BWController object from Tox and friend number */ + ToxAV *toxav = (ToxAV *)tox_get_av_object(tox); + + if (!toxav) { + LOGGER_API_ERROR(tox, "Could not get ToxAV object from Tox"); + return; + } + + void *call = (void *)call_get(toxav, friendnumber); + + if (!call) { + LOGGER_API_ERROR(tox, "Could not get ToxAVCall object from ToxAV"); + return; + } + + /* get Call object from Tox and friend number */ + BWController *bwc = bwc_controller_get(call); + + if (!bwc) { + LOGGER_API_WARNING(tox, "No session!"); + return; + } + + if (!bwc->bwc_receive_active) { + LOGGER_API_WARNING(tox, "receiving not allowed!"); + return; + } + + size_t offset = 1; // Ignore packet id. + struct BWCMessage msg; + offset += net_unpack_u32(data + offset, &msg.lost); + offset += net_unpack_u32(data + offset, &msg.recv); + assert(offset == length); + + on_update(bwc, &msg); +} + /* * return -1 on failure, 0 on success * @@ -202,17 +243,12 @@ static int bwc_send_custom_lossy_packet(Tox *tox, int32_t friendnumber, const ui return -1; } -static int bwc_handle_data(Messenger *m, uint32_t friendnumber, const uint8_t *data, uint16_t length, void *object) +void bwc_allow_receiving(Tox *tox) { - if (length - 1 != sizeof(struct BWCMessage)) { - return -1; - } - - size_t offset = 1; // Ignore packet id. - struct BWCMessage msg; - offset += net_unpack_u32(data + offset, &msg.lost); - offset += net_unpack_u32(data + offset, &msg.recv); - assert(offset == length); + tox_callback_friend_lossy_packet_per_pktid(tox, bwc_handle_data, BWC_PACKET_ID); +} - return on_update((BWController *)object, &msg); +void bwc_stop_receiving(Tox *tox) +{ + tox_callback_friend_lossy_packet_per_pktid(tox, nullptr, BWC_PACKET_ID); } diff --git a/toxav/bwcontroller.h b/toxav/bwcontroller.h index 9470c125eb..edce3e987a 100644 --- a/toxav/bwcontroller.h +++ b/toxav/bwcontroller.h @@ -5,8 +5,10 @@ #ifndef C_TOXCORE_TOXAV_BWCONTROLLER_H #define C_TOXCORE_TOXAV_BWCONTROLLER_H -#include "../toxcore/Messenger.h" +#include + #include "../toxcore/tox.h" +#include "../toxcore/mono_time.h" #ifndef TOX_DEFINED #define TOX_DEFINED @@ -17,12 +19,14 @@ typedef struct BWController_s BWController; typedef void m_cb(BWController *bwc, uint32_t friend_number, float todo, void *user_data); -BWController *bwc_new(Messenger *m, Tox *tox, uint32_t friendnumber, m_cb *mcb, void *mcb_user_data, +BWController *bwc_new(Tox *tox, uint32_t friendnumber, m_cb *mcb, void *mcb_user_data, Mono_Time *bwc_mono_time); void bwc_kill(BWController *bwc); void bwc_add_lost(BWController *bwc, uint32_t bytes_lost); void bwc_add_recv(BWController *bwc, uint32_t recv_bytes); +void bwc_allow_receiving(Tox *tox); +void bwc_stop_receiving(Tox *tox); #endif // C_TOXCORE_TOXAV_BWCONTROLLER_H diff --git a/toxav/msi.c b/toxav/msi.c index 4772ac8ab3..cb8e479976 100644 --- a/toxav/msi.c +++ b/toxav/msi.c @@ -7,9 +7,13 @@ #endif /* HAVE_CONFIG_H */ #include "msi.h" +#include "toxav_hacks.h" +#include "../toxcore/tox.h" +#include "../toxcore/tox_private.h" #include "../toxcore/logger.h" #include "../toxcore/util.h" +#include "../toxcore/net_crypto.h" #include #include @@ -18,6 +22,11 @@ #define MSI_MAXMSG_SIZE 256 +#ifndef TOXAV_DEFINED +#define TOXAV_DEFINED +typedef struct ToxAV ToxAV; +#endif /* TOXAV_DEFINED */ + /** * Protocol: * @@ -62,20 +71,17 @@ typedef struct MSIMessage { static void msg_init(MSIMessage *dest, MSIRequest request); -static int msg_parse_in(const Logger *log, MSIMessage *dest, const uint8_t *data, uint16_t length); +static int msg_parse_in(Tox *tox, MSIMessage *dest, const uint8_t *data, uint16_t length); static uint8_t *msg_parse_header_out(MSIHeaderID id, uint8_t *dest, const void *value, uint8_t value_len, uint16_t *length); -static int send_message(Messenger *m, uint32_t friend_number, const MSIMessage *msg); -static int send_error(Messenger *m, uint32_t friend_number, MSIError error); -static int invoke_callback(MSICall *call, MSICallbackID cb); +static int send_message(Tox *tox, uint32_t friend_number, const MSIMessage *msg); +static int send_error(Tox *tox, uint32_t friend_number, MSIError error); static MSICall *get_call(MSISession *session, uint32_t friend_number); static MSICall *new_call(MSISession *session, uint32_t friend_number); -static void kill_call(MSICall *call); -static void on_peer_status(Messenger *m, uint32_t friend_number, uint8_t status, void *data); static void handle_init(MSICall *call, const MSIMessage *msg); static void handle_push(MSICall *call, const MSIMessage *msg); static void handle_pop(MSICall *call, const MSIMessage *msg); -static void handle_msi_packet(Messenger *m, uint32_t friend_number, const uint8_t *data, uint16_t length, void *object); +static void handle_msi_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length2, void *object); /** @@ -91,46 +97,47 @@ void msi_register_callback(MSISession *session, msi_action_cb *callback, MSICall session->callbacks[id] = callback; pthread_mutex_unlock(session->mutex); } -MSISession *msi_new(Messenger *m) + +MSISession *msi_new(Tox *tox) { - if (m == nullptr) { + if (tox == nullptr) { return nullptr; } MSISession *retu = (MSISession *)calloc(sizeof(MSISession), 1); if (retu == nullptr) { - LOGGER_ERROR(m->log, "Allocation failed! Program might misbehave!"); + LOGGER_API_ERROR(tox, "Allocation failed! Program might misbehave!"); return nullptr; } if (create_recursive_mutex(retu->mutex) != 0) { - LOGGER_ERROR(m->log, "Failed to init mutex! Program might misbehave"); + LOGGER_API_ERROR(tox, "Failed to init mutex! Program might misbehave"); free(retu); return nullptr; } - retu->messenger = m; - - m_callback_msi_packet(m, handle_msi_packet, retu); + retu->tox = tox; - /* This is called when remote terminates session */ - m_callback_connectionstatus_internal_av(m, on_peer_status, retu); + // register callback + tox_callback_friend_lossless_packet_per_pktid(tox, handle_msi_packet, PACKET_ID_MSI); - LOGGER_DEBUG(m->log, "New msi session: %p ", (void *)retu); + LOGGER_API_DEBUG(tox, "New msi session: %p ", (void *)retu); return retu; } -int msi_kill(MSISession *session, const Logger *log) + +int msi_kill(Tox *tox, MSISession *session, const Logger *log) { if (session == nullptr) { - LOGGER_ERROR(log, "Tried to terminate non-existing session"); + LOGGER_API_ERROR(tox, "Tried to terminate non-existing session"); return -1; } - m_callback_msi_packet(session->messenger, nullptr, nullptr); + // UN-register callback + tox_callback_friend_lossless_packet_per_pktid(tox, nullptr, PACKET_ID_MSI); if (pthread_mutex_trylock(session->mutex) != 0) { - LOGGER_ERROR(log, "Failed to acquire lock on msi mutex"); + LOGGER_API_ERROR(tox, "Failed to acquire lock on msi mutex"); return -1; } @@ -141,7 +148,7 @@ int msi_kill(MSISession *session, const Logger *log) MSICall *it = get_call(session, session->calls_head); while (it) { - send_message(session->messenger, it->friend_number, &msg); + send_message(session->tox, it->friend_number, &msg); MSICall *temp_it = it; it = it->next; kill_call(temp_it); /* This will eventually free session->calls */ @@ -151,25 +158,65 @@ int msi_kill(MSISession *session, const Logger *log) pthread_mutex_unlock(session->mutex); pthread_mutex_destroy(session->mutex); - LOGGER_DEBUG(log, "Terminated session: %p", (void *)session); + LOGGER_API_DEBUG(tox, "Terminated session: %p", (void *)session); free(session); return 0; } + +/* + * return true if friend was offline and the call was canceled + */ +bool check_peer_offline_status(Tox *tox, MSISession *session, uint32_t friend_number) +{ + if (!tox) { + return false; + } + + if (!session) { + return false; + } + + Tox_Err_Friend_Query f_con_query_error; + Tox_Connection f_conn_status = tox_friend_get_connection_status(tox, friend_number, &f_con_query_error); + + if (f_conn_status == TOX_CONNECTION_NONE) { + /* Friend is now offline */ + LOGGER_API_DEBUG(tox, "Friend %d is now offline", friend_number); + + pthread_mutex_lock(session->mutex); + MSICall *call = get_call(session, friend_number); + + if (call == nullptr) { + pthread_mutex_unlock(session->mutex); + return true; + } + + invoke_callback(call, MSI_ON_PEERTIMEOUT); /* Failure is ignored */ + kill_call(call); + pthread_mutex_unlock(session->mutex); + return true; + } + + return false; +} + int msi_invite(MSISession *session, MSICall **call, uint32_t friend_number, uint8_t capabilities) { + LOGGER_API_DEBUG(session->tox, "msi_invite:session:%p", (void *)session); + if (!session) { return -1; } - LOGGER_DEBUG(session->messenger->log, "Session: %p Inviting friend: %u", (void *)session, friend_number); + LOGGER_API_DEBUG(session->tox, "Session: %p Inviting friend: %u", (void *)session, friend_number); if (pthread_mutex_trylock(session->mutex) != 0) { - LOGGER_ERROR(session->messenger->log, "Failed to acquire lock on msi mutex"); + LOGGER_API_ERROR(session->tox, "Failed to acquire lock on msi mutex"); return -1; } if (get_call(session, friend_number) != nullptr) { - LOGGER_ERROR(session->messenger->log, "Already in a call"); + LOGGER_API_ERROR(session->tox, "Already in a call"); pthread_mutex_unlock(session->mutex); return -1; } @@ -189,16 +236,17 @@ int msi_invite(MSISession *session, MSICall **call, uint32_t friend_number, uint msg.capabilities.exists = true; msg.capabilities.value = capabilities; - send_message(temp->session->messenger, temp->friend_number, &msg); + send_message(temp->session->tox, temp->friend_number, &msg); temp->state = MSI_CALL_REQUESTING; *call = temp; - LOGGER_DEBUG(session->messenger->log, "Invite sent"); + LOGGER_API_DEBUG(session->tox, "Invite sent"); pthread_mutex_unlock(session->mutex); return 0; } + int msi_hangup(MSICall *call) { if (!call || !call->session) { @@ -207,16 +255,16 @@ int msi_hangup(MSICall *call) MSISession *session = call->session; - LOGGER_DEBUG(session->messenger->log, "Session: %p Hanging up call with friend: %u", (void *)call->session, - call->friend_number); + LOGGER_API_DEBUG(session->tox, "Session: %p Hanging up call with friend: %u", (void *)call->session, + call->friend_number); if (pthread_mutex_trylock(session->mutex) != 0) { - LOGGER_ERROR(session->messenger->log, "Failed to acquire lock on msi mutex"); + LOGGER_API_ERROR(session->tox, "Failed to acquire lock on msi mutex"); return -1; } if (call->state == MSI_CALL_INACTIVE) { - LOGGER_ERROR(session->messenger->log, "Call is in invalid state!"); + LOGGER_API_ERROR(session->tox, "Call is in invalid state!"); pthread_mutex_unlock(session->mutex); return -1; } @@ -224,12 +272,13 @@ int msi_hangup(MSICall *call) MSIMessage msg; msg_init(&msg, REQU_POP); - send_message(session->messenger, call->friend_number, &msg); + send_message(session->tox, call->friend_number, &msg); kill_call(call); pthread_mutex_unlock(session->mutex); return 0; } + int msi_answer(MSICall *call, uint8_t capabilities) { if (!call || !call->session) { @@ -238,18 +287,18 @@ int msi_answer(MSICall *call, uint8_t capabilities) MSISession *session = call->session; - LOGGER_DEBUG(session->messenger->log, "Session: %p Answering call from: %u", (void *)call->session, - call->friend_number); + LOGGER_API_DEBUG(session->tox, "Session: %p Answering call from: %u", (void *)call->session, + call->friend_number); if (pthread_mutex_trylock(session->mutex) != 0) { - LOGGER_ERROR(session->messenger->log, "Failed to acquire lock on msi mutex"); + LOGGER_API_ERROR(session->tox, "Failed to acquire lock on msi mutex"); return -1; } if (call->state != MSI_CALL_REQUESTED) { /* Though sending in invalid state will not cause anything weird * Its better to not do it like a maniac */ - LOGGER_ERROR(session->messenger->log, "Call is in invalid state!"); + LOGGER_API_ERROR(session->tox, "Call is in invalid state!"); pthread_mutex_unlock(session->mutex); return -1; } @@ -262,13 +311,14 @@ int msi_answer(MSICall *call, uint8_t capabilities) msg.capabilities.exists = true; msg.capabilities.value = capabilities; - send_message(session->messenger, call->friend_number, &msg); + send_message(session->tox, call->friend_number, &msg); call->state = MSI_CALL_ACTIVE; pthread_mutex_unlock(session->mutex); return 0; } + int msi_change_capabilities(MSICall *call, uint8_t capabilities) { if (!call || !call->session) { @@ -277,16 +327,16 @@ int msi_change_capabilities(MSICall *call, uint8_t capabilities) MSISession *session = call->session; - LOGGER_DEBUG(session->messenger->log, "Session: %p Trying to change capabilities to friend %u", (void *)call->session, - call->friend_number); + LOGGER_API_DEBUG(session->tox, "Session: %p Trying to change capabilities to friend %u", (void *)call->session, + call->friend_number); if (pthread_mutex_trylock(session->mutex) != 0) { - LOGGER_ERROR(session->messenger->log, "Failed to acquire lock on msi mutex"); + LOGGER_API_ERROR(session->tox, "Failed to acquire lock on msi mutex"); return -1; } if (call->state != MSI_CALL_ACTIVE) { - LOGGER_ERROR(session->messenger->log, "Call is in invalid state!"); + LOGGER_API_ERROR(session->tox, "Call is in invalid state!"); pthread_mutex_unlock(session->mutex); return -1; } @@ -299,7 +349,7 @@ int msi_change_capabilities(MSICall *call, uint8_t capabilities) msg.capabilities.exists = true; msg.capabilities.value = capabilities; - send_message(call->session->messenger, call->friend_number, &msg); + send_message(call->session->tox, call->friend_number, &msg); pthread_mutex_unlock(session->mutex); return 0; @@ -315,7 +365,8 @@ static void msg_init(MSIMessage *dest, MSIRequest request) dest->request.exists = true; dest->request.value = request; } -static int msg_parse_in(const Logger *log, MSIMessage *dest, const uint8_t *data, uint16_t length) + +static int msg_parse_in(Tox *tox, MSIMessage *dest, const uint8_t *data, uint16_t length) { /* Parse raw data received from socket into MSIMessage struct */ @@ -323,11 +374,11 @@ static int msg_parse_in(const Logger *log, MSIMessage *dest, const uint8_t *data do { \ constraint -= 2 + size; \ if (constraint < 1) { \ - LOGGER_ERROR(log, "Read over length!"); \ + LOGGER_API_ERROR(tox, "Read over length!"); \ return -1; \ } \ if (bytes[1] != size) { \ - LOGGER_ERROR(log, "Invalid data size!"); \ + LOGGER_API_ERROR(tox, "Invalid data size!"); \ return -1; \ } \ } while (0) @@ -336,7 +387,7 @@ static int msg_parse_in(const Logger *log, MSIMessage *dest, const uint8_t *data #define CHECK_ENUM_HIGH(bytes, enum_high) \ do { \ if (bytes[2] > enum_high) { \ - LOGGER_ERROR(log, "Failed enum high limit!"); \ + LOGGER_API_ERROR(tox, "Failed enum high limit!"); \ return -1; \ } \ } while (0) @@ -344,7 +395,7 @@ static int msg_parse_in(const Logger *log, MSIMessage *dest, const uint8_t *data assert(dest); if (length == 0 || data[length - 1]) { /* End byte must have value 0 */ - LOGGER_ERROR(log, "Invalid end byte"); + LOGGER_API_ERROR(tox, "Invalid end byte"); return -1; } @@ -379,13 +430,13 @@ static int msg_parse_in(const Logger *log, MSIMessage *dest, const uint8_t *data break; default: - LOGGER_ERROR(log, "Invalid id byte"); + LOGGER_API_ERROR(tox, "Invalid id byte"); return -1; } } if (dest->request.exists == false) { - LOGGER_ERROR(log, "Invalid request field!"); + LOGGER_API_ERROR(tox, "Invalid request field!"); return -1; } @@ -394,6 +445,7 @@ static int msg_parse_in(const Logger *log, MSIMessage *dest, const uint8_t *data return 0; } + static uint8_t *msg_parse_header_out(MSIHeaderID id, uint8_t *dest, const void *value, uint8_t value_len, uint16_t *length) { @@ -413,10 +465,49 @@ static uint8_t *msg_parse_header_out(MSIHeaderID id, uint8_t *dest, const void * return dest + value_len; /* Set to next position ready to be written */ } -static int send_message(Messenger *m, uint32_t friend_number, const MSIMessage *msg) + +/* Send an msi packet. + * + * return 1 on success + * return 0 on failure + */ +static int m_msi_packet(Tox *tox, int32_t friendnumber, const uint8_t *data, uint16_t length) +{ + // TODO(Zoff): make this better later! ------------------- + size_t length_new = length + 1; + uint8_t *data_new = (uint8_t *)calloc(1, length_new); + + if (!data_new) { + return 0; + } + + data_new[0] = PACKET_ID_MSI; + + if (length != 0) { + memcpy(data_new + 1, data, length); + } + + // TODO(Zoff): make this better later! ------------------- + + Tox_Err_Friend_Custom_Packet error; + tox_friend_send_lossless_packet(tox, friendnumber, data_new, length_new, &error); + + // TODO(Zoff): make this better later! ------------------- + free(data_new); + // TODO(Zoff): make this better later! ------------------- + + if (error == TOX_ERR_FRIEND_CUSTOM_PACKET_OK) { + return 1; + } + + return 0; +} + +static int send_message(Tox *tox, uint32_t friend_number, const MSIMessage *msg) { + assert(tox); + /* Parse and send message */ - assert(m); uint8_t parsed [MSI_MAXMSG_SIZE]; @@ -428,7 +519,7 @@ static int send_message(Messenger *m, uint32_t friend_number, const MSIMessage * it = msg_parse_header_out(ID_REQUEST, it, &cast, sizeof(cast), &size); } else { - LOGGER_DEBUG(m->log, "Must have request field"); + LOGGER_API_DEBUG(tox, "Must have request field"); return -1; } @@ -444,26 +535,28 @@ static int send_message(Messenger *m, uint32_t friend_number, const MSIMessage * } if (it == parsed) { - LOGGER_WARNING(m->log, "Parsing message failed; empty message"); + LOGGER_API_WARNING(tox, "Parsing message failed; empty message"); return -1; } *it = 0; ++size; - if (m_msi_packet(m, friend_number, parsed, size)) { - LOGGER_DEBUG(m->log, "Sent message"); + if (m_msi_packet(tox, friend_number, parsed, size)) { + LOGGER_API_DEBUG(tox, "Sent message"); return 0; } return -1; } -static int send_error(Messenger *m, uint32_t friend_number, MSIError error) + +static int send_error(Tox *tox, uint32_t friend_number, MSIError error) { + assert(tox); + /* Send error message */ - assert(m); - LOGGER_DEBUG(m->log, "Sending error: %d to friend: %d", error, friend_number); + LOGGER_API_DEBUG(tox, "Sending error: %d to friend: %d", error, friend_number); MSIMessage msg; msg_init(&msg, REQU_POP); @@ -471,19 +564,20 @@ static int send_error(Messenger *m, uint32_t friend_number, MSIError error) msg.error.exists = true; msg.error.value = error; - send_message(m, friend_number, &msg); + send_message(tox, friend_number, &msg); return 0; } -static int invoke_callback(MSICall *call, MSICallbackID cb) + +int invoke_callback(MSICall *call, MSICallbackID cb) { assert(call); if (call->session->callbacks[cb]) { - LOGGER_DEBUG(call->session->messenger->log, "Invoking callback function: %d", cb); + LOGGER_API_DEBUG(call->session->tox, "Invoking callback function: %d", cb); if (call->session->callbacks[cb](call->session->av, call) != 0) { - LOGGER_WARNING(call->session->messenger->log, - "Callback state handling failed, sending error"); + LOGGER_API_WARNING(call->session->tox, + "Callback state handling failed, sending error"); goto FAILURE; } @@ -501,6 +595,7 @@ static int invoke_callback(MSICall *call, MSICallbackID cb) return -1; } + static MSICall *get_call(MSISession *session, uint32_t friend_number) { assert(session); @@ -511,6 +606,7 @@ static MSICall *get_call(MSISession *session, uint32_t friend_number) return session->calls[friend_number]; } + static MSICall *new_call(MSISession *session, uint32_t friend_number) { assert(session); @@ -564,7 +660,8 @@ static MSICall *new_call(MSISession *session, uint32_t friend_number) session->calls[friend_number] = rc; return rc; } -static void kill_call(MSICall *call) + +void kill_call(MSICall *call) { /* Assume that session mutex is locked */ if (call == nullptr) { @@ -573,7 +670,7 @@ static void kill_call(MSICall *call) MSISession *session = call->session; - LOGGER_DEBUG(session->messenger->log, "Killing call: %p", (void *)call); + LOGGER_API_DEBUG(session->tox, "Killing call: %p", (void *)call); MSICall *prev = call->prev; MSICall *next = call->next; @@ -605,40 +702,16 @@ static void kill_call(MSICall *call) free(call); session->calls = nullptr; } -static void on_peer_status(Messenger *m, uint32_t friend_number, uint8_t status, void *data) -{ - MSISession *session = (MSISession *)data; - - switch (status) { - case 0: { /* Friend is now offline */ - LOGGER_DEBUG(m->log, "Friend %d is now offline", friend_number); - pthread_mutex_lock(session->mutex); - MSICall *call = get_call(session, friend_number); - - if (call == nullptr) { - pthread_mutex_unlock(session->mutex); - return; - } - - invoke_callback(call, MSI_ON_PEERTIMEOUT); /* Failure is ignored */ - kill_call(call); - pthread_mutex_unlock(session->mutex); - } - break; - default: - break; - } -} static void handle_init(MSICall *call, const MSIMessage *msg) { assert(call); - LOGGER_DEBUG(call->session->messenger->log, - "Session: %p Handling 'init' friend: %d", (void *)call->session, call->friend_number); + LOGGER_API_DEBUG(call->session->tox, + "Session: %p Handling 'init' friend: %d", (void *)call->session, call->friend_number); if (!msg->capabilities.exists) { - LOGGER_WARNING(call->session->messenger->log, "Session: %p Invalid capabilities on 'init'", (void *)call->session); + LOGGER_API_WARNING(call->session->tox, "Session: %p Invalid capabilities on 'init'", (void *)call->session); call->error = MSI_E_INVALID_MESSAGE; goto FAILURE; } @@ -663,7 +736,7 @@ static void handle_init(MSICall *call, const MSIMessage *msg) * we can automatically answer the re-call. */ - LOGGER_INFO(call->session->messenger->log, "Friend is recalling us"); + LOGGER_API_INFO(call->session->tox, "Friend is recalling us"); MSIMessage out_msg; msg_init(&out_msg, REQU_PUSH); @@ -671,7 +744,7 @@ static void handle_init(MSICall *call, const MSIMessage *msg) out_msg.capabilities.exists = true; out_msg.capabilities.value = call->self_capabilities; - send_message(call->session->messenger, call->friend_number, &out_msg); + send_message(call->session->tox, call->friend_number, &out_msg); /* If peer changed capabilities during re-call they will * be handled accordingly during the next step @@ -681,7 +754,7 @@ static void handle_init(MSICall *call, const MSIMessage *msg) case MSI_CALL_REQUESTED: // fall-through case MSI_CALL_REQUESTING: { - LOGGER_WARNING(call->session->messenger->log, "Session: %p Invalid state on 'init'", (void *)call->session); + LOGGER_API_WARNING(call->session->tox, "Session: %p Invalid state on 'init'", (void *)call->session); call->error = MSI_E_INVALID_STATE; goto FAILURE; } @@ -689,18 +762,19 @@ static void handle_init(MSICall *call, const MSIMessage *msg) return; FAILURE: - send_error(call->session->messenger, call->friend_number, call->error); + send_error(call->session->tox, call->friend_number, call->error); kill_call(call); } + static void handle_push(MSICall *call, const MSIMessage *msg) { assert(call); - LOGGER_DEBUG(call->session->messenger->log, "Session: %p Handling 'push' friend: %d", (void *)call->session, - call->friend_number); + LOGGER_API_DEBUG(call->session->tox, "Session: %p Handling 'push' friend: %d", (void *)call->session, + call->friend_number); if (!msg->capabilities.exists) { - LOGGER_WARNING(call->session->messenger->log, "Session: %p Invalid capabilities on 'push'", (void *)call->session); + LOGGER_API_WARNING(call->session->tox, "Session: %p Invalid capabilities on 'push'", (void *)call->session); call->error = MSI_E_INVALID_MESSAGE; goto FAILURE; } @@ -709,7 +783,7 @@ static void handle_push(MSICall *call, const MSIMessage *msg) case MSI_CALL_ACTIVE: { /* Only act if capabilities changed */ if (call->peer_capabilities != msg->capabilities.value) { - LOGGER_INFO(call->session->messenger->log, "Friend is changing capabilities to: %u", msg->capabilities.value); + LOGGER_API_INFO(call->session->tox, "Friend is changing capabilities to: %u", msg->capabilities.value); call->peer_capabilities = msg->capabilities.value; @@ -721,7 +795,7 @@ static void handle_push(MSICall *call, const MSIMessage *msg) break; case MSI_CALL_REQUESTING: { - LOGGER_INFO(call->session->messenger->log, "Friend answered our call"); + LOGGER_API_INFO(call->session->tox, "Friend answered our call"); /* Call started */ call->peer_capabilities = msg->capabilities.value; @@ -736,7 +810,7 @@ static void handle_push(MSICall *call, const MSIMessage *msg) /* Pushes during initialization state are ignored */ case MSI_CALL_INACTIVE: // fall-through case MSI_CALL_REQUESTED: { - LOGGER_WARNING(call->session->messenger->log, "Ignoring invalid push"); + LOGGER_API_WARNING(call->session->tox, "Ignoring invalid push"); } break; } @@ -744,46 +818,47 @@ static void handle_push(MSICall *call, const MSIMessage *msg) return; FAILURE: - send_error(call->session->messenger, call->friend_number, call->error); + send_error(call->session->tox, call->friend_number, call->error); kill_call(call); } + static void handle_pop(MSICall *call, const MSIMessage *msg) { assert(call); - LOGGER_DEBUG(call->session->messenger->log, "Session: %p Handling 'pop', friend id: %d", (void *)call->session, - call->friend_number); + LOGGER_API_DEBUG(call->session->tox, "Session: %p Handling 'pop', friend id: %d", (void *)call->session, + call->friend_number); /* callback errors are ignored */ if (msg->error.exists) { - LOGGER_WARNING(call->session->messenger->log, "Friend detected an error: %d", msg->error.value); + LOGGER_API_WARNING(call->session->tox, "Friend detected an error: %d", msg->error.value); call->error = msg->error.value; invoke_callback(call, MSI_ON_ERROR); } else { switch (call->state) { case MSI_CALL_INACTIVE: { - LOGGER_ERROR(call->session->messenger->log, "Handling what should be impossible case"); + LOGGER_API_ERROR(call->session->tox, "Handling what should be impossible case"); abort(); } case MSI_CALL_ACTIVE: { /* Hangup */ - LOGGER_INFO(call->session->messenger->log, "Friend hung up on us"); + LOGGER_API_INFO(call->session->tox, "Friend hung up on us"); invoke_callback(call, MSI_ON_END); } break; case MSI_CALL_REQUESTING: { /* Reject */ - LOGGER_INFO(call->session->messenger->log, "Friend rejected our call"); + LOGGER_API_INFO(call->session->tox, "Friend rejected our call"); invoke_callback(call, MSI_ON_END); } break; case MSI_CALL_REQUESTED: { /* Cancel */ - LOGGER_INFO(call->session->messenger->log, "Friend canceled call invite"); + LOGGER_API_INFO(call->session->tox, "Friend canceled call invite"); invoke_callback(call, MSI_ON_END); } break; @@ -792,27 +867,50 @@ static void handle_pop(MSICall *call, const MSIMessage *msg) kill_call(call); } -static void handle_msi_packet(Messenger *m, uint32_t friend_number, const uint8_t *data, uint16_t length, void *object) + +static void handle_msi_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length2, void *object) { - LOGGER_DEBUG(m->log, "Got msi message"); + if (length2 < 2) { + // we need more than the ID byte for MSI messages + return; + } + + // Zoff: is this correct? + uint16_t length = (uint16_t)(length2 - 1); + + // Zoff: do not show the first byte, its always "PACKET_ID_MSI" + const uint8_t *data_strip_id_byte = (const uint8_t *)(data + 1); + + LOGGER_API_DEBUG(tox, "Got msi message"); + + ToxAV *toxav = (ToxAV *)tox_get_av_object(tox); + + if (!toxav) { + return; + } + + MSISession *session = tox_av_msi_get(toxav); + + if (!session) { + return; + } - MSISession *session = (MSISession *)object; MSIMessage msg; - if (msg_parse_in(m->log, &msg, data, length) == -1) { - LOGGER_WARNING(m->log, "Error parsing message"); - send_error(m, friend_number, MSI_E_INVALID_MESSAGE); + if (msg_parse_in(session->tox, &msg, data_strip_id_byte, length) == -1) { + LOGGER_API_WARNING(tox, "Error parsing message"); + send_error(tox, friend_number, MSI_E_INVALID_MESSAGE); return; } - LOGGER_DEBUG(m->log, "Successfully parsed message"); + LOGGER_API_DEBUG(tox, "Successfully parsed message"); pthread_mutex_lock(session->mutex); MSICall *call = get_call(session, friend_number); if (call == nullptr) { if (msg.request.value != REQU_INIT) { - send_error(m, friend_number, MSI_E_STRAY_MESSAGE); + send_error(tox, friend_number, MSI_E_STRAY_MESSAGE); pthread_mutex_unlock(session->mutex); return; } @@ -820,7 +918,7 @@ static void handle_msi_packet(Messenger *m, uint32_t friend_number, const uint8_ call = new_call(session, friend_number); if (call == nullptr) { - send_error(m, friend_number, MSI_E_SYSTEM); + send_error(tox, friend_number, MSI_E_SYSTEM); pthread_mutex_unlock(session->mutex); return; } diff --git a/toxav/msi.h b/toxav/msi.h index 5809228db2..d713ce376f 100644 --- a/toxav/msi.h +++ b/toxav/msi.h @@ -8,7 +8,6 @@ #include "audio.h" #include "video.h" -#include "../toxcore/Messenger.h" #include "../toxcore/logger.h" #include @@ -43,22 +42,22 @@ typedef enum MSICapabilities { * Call state identifiers. */ typedef enum MSICallState { - MSI_CALL_INACTIVE, /* Default */ - MSI_CALL_ACTIVE, - MSI_CALL_REQUESTING, /* when sending call invite */ - MSI_CALL_REQUESTED, /* when getting call invite */ + MSI_CALL_INACTIVE = 0, /* Default */ + MSI_CALL_ACTIVE = 1, + MSI_CALL_REQUESTING = 2, /* when sending call invite */ + MSI_CALL_REQUESTED = 3, /* when getting call invite */ } MSICallState; /** * Callbacks ids that handle the states */ typedef enum MSICallbackID { - MSI_ON_INVITE, /* Incoming call */ - MSI_ON_START, /* Call (RTP transmission) started */ - MSI_ON_END, /* Call that was active ended */ - MSI_ON_ERROR, /* On protocol error */ - MSI_ON_PEERTIMEOUT, /* Peer timed out; stop the call */ - MSI_ON_CAPABILITIES, /* Peer requested capabilities change */ + MSI_ON_INVITE = 0, /* Incoming call */ + MSI_ON_START = 1, /* Call (RTP transmission) started */ + MSI_ON_END = 2, /* Call that was active ended */ + MSI_ON_ERROR = 3, /* On protocol error */ + MSI_ON_PEERTIMEOUT = 4, /* Peer timed out; stop the call */ + MSI_ON_CAPABILITIES = 5, /* Peer requested capabilities change */ } MSICallbackID; /** @@ -74,7 +73,7 @@ typedef struct MSICall_s { uint32_t friend_number; /* Index of this call in MSISession */ MSIError error; /* Last error */ - struct ToxAVCall_s *av_call; /* Pointer to av call handler */ + struct ToxAVCall *av_call; /* Pointer to av call handler */ struct MSICall_s *next; struct MSICall_s *prev; @@ -98,7 +97,7 @@ typedef struct MSISession_s { uint32_t calls_head; void *av; - Messenger *messenger; + Tox *tox; pthread_mutex_t mutex[1]; msi_action_cb *callbacks[7]; @@ -107,11 +106,11 @@ typedef struct MSISession_s { /** * Start the control session. */ -MSISession *msi_new(Messenger *m); +MSISession *msi_new(Tox *tox); /** * Terminate control session. NOTE: all calls will be freed */ -int msi_kill(MSISession *session, const Logger *log); +int msi_kill(Tox *tox, MSISession *session, const Logger *log); /** * Callback setter. */ @@ -133,4 +132,8 @@ int msi_answer(MSICall *call, uint8_t capabilities); */ int msi_change_capabilities(MSICall *call, uint8_t capabilities); +int invoke_callback(MSICall *call, MSICallbackID cb); +void kill_call(MSICall *call); +bool check_peer_offline_status(Tox *tox, MSISession *session, uint32_t friend_number); + #endif // C_TOXCORE_TOXAV_MSI_H diff --git a/toxav/rtp.c b/toxav/rtp.c index 69aed2dc05..302d264053 100644 --- a/toxav/rtp.c +++ b/toxav/rtp.c @@ -7,6 +7,7 @@ #endif /* HAVE_CONFIG_H */ #include "rtp.h" +#include "toxav_hacks.h" #include #include @@ -15,10 +16,13 @@ #include "bwcontroller.h" -#include "../toxcore/Messenger.h" #include "../toxcore/logger.h" #include "../toxcore/mono_time.h" #include "../toxcore/util.h" +#include "../toxcore/net_crypto.h" +#include "../toxcore/tox_private.h" + +static int rtp_send_custom_lossy_packet(Tox *tox, int32_t friendnumber, const uint8_t *data, uint32_t length); /** * The number of milliseconds we want to keep a keyframe in the buffer for, @@ -26,7 +30,6 @@ */ #define VIDEO_KEEP_KEYFRAME_IN_BUFFER_FOR_MS 15 - /* * return -1 on failure, 0 on success * @@ -43,15 +46,22 @@ static int rtp_send_custom_lossy_packet(Tox *tox, int32_t friendnumber, const ui return -1; } + // allocate_len is NOT including header! -static struct RTPMessage *new_message(const struct RTPHeader *header, size_t allocate_len, const uint8_t *data, +static struct RTPMessage *new_message(Tox *tox, const struct RTPHeader *header, size_t allocate_len, + const uint8_t *data, uint16_t data_length) { assert(allocate_len >= data_length); struct RTPMessage *msg = (struct RTPMessage *)calloc(1, sizeof(struct RTPMessage) + allocate_len); if (msg == nullptr) { + LOGGER_API_DEBUG(tox, "%s:%d:%s:msg=calloc(%d):NULL", __FILE__, __LINE__, __func__, + (int)(sizeof(struct RTPMessage) + allocate_len)); return nullptr; + } else { + LOGGER_API_DEBUG(tox, "%s:%d:%s:msg=calloc(%d):%p", __FILE__, __LINE__, __func__, + (int)(sizeof(struct RTPMessage) + allocate_len), (void *)msg); } msg->len = data_length; // result without header @@ -82,7 +92,7 @@ static struct RTPMessage *new_message(const struct RTPHeader *header, size_t all * do not kick it out right away if all slots are full instead kick out the new * incoming interframe. */ -static int8_t get_slot(const Logger *log, struct RTPWorkBufferList *wkbl, bool is_keyframe, +static int8_t get_slot(Tox *tox, struct RTPWorkBufferList *wkbl, bool is_keyframe, const struct RTPHeader *header, bool is_multipart) { if (is_multipart) { @@ -143,7 +153,7 @@ static int8_t get_slot(const Logger *log, struct RTPWorkBufferList *wkbl, bool i // If the incoming packet is older than our newest slot, drop it. // This is the first situation in the above diagram. if (slot->buf->header.timestamp > header->timestamp) { - LOGGER_DEBUG(log, "workbuffer:2:timestamp too old"); + LOGGER_API_DEBUG(tox, "workbuffer:2:timestamp too old"); return GET_SLOT_RESULT_DROP_INCOMING; } } @@ -186,7 +196,7 @@ static int8_t get_slot(const Logger *log, struct RTPWorkBufferList *wkbl, bool i // This is a key frame, it's not too old yet, so we keep it in its slot for // a little longer. - LOGGER_INFO(log, "keep KEYFRAME in workbuffer"); + LOGGER_API_INFO(tox, "keep KEYFRAME in workbuffer"); return GET_SLOT_RESULT_DROP_INCOMING; } @@ -198,7 +208,7 @@ static int8_t get_slot(const Logger *log, struct RTPWorkBufferList *wkbl, bool i * non-NULL, it transfers ownership of the message to the caller, i.e. the * caller is responsible for storing it elsewhere or calling free(). */ -static struct RTPMessage *process_frame(const Logger *log, struct RTPWorkBufferList *wkbl, uint8_t slot_id) +static struct RTPMessage *process_frame(Tox *tox, struct RTPWorkBufferList *wkbl, uint8_t slot_id) { assert(wkbl->next_free_entry >= 0); @@ -210,7 +220,7 @@ static struct RTPMessage *process_frame(const Logger *log, struct RTPWorkBufferL // Slot 0 contains a key frame, slot_id points at an interframe that is // relative to that key frame, so we don't use it yet. if (wkbl->work_buffer[0].is_keyframe && slot_id != 0) { - LOGGER_DEBUG(log, "process_frame:KEYFRAME waiting in slot 0"); + LOGGER_API_DEBUG(tox, "process_frame:KEYFRAME waiting in slot 0"); return nullptr; } @@ -245,7 +255,7 @@ static struct RTPMessage *process_frame(const Logger *log, struct RTPWorkBufferL } /** - * @param log A logger. + * @param tox pointer to Tox * @param wkbl The list of in-progress frames, i.e. all the slots. * @param slot_id The slot we want to fill the data into. * @param is_keyframe Whether the data is part of a key frame. @@ -253,7 +263,7 @@ static struct RTPMessage *process_frame(const Logger *log, struct RTPWorkBufferL * @param incoming_data The pure payload without header. * @param incoming_data_length The length in bytes of the incoming data payload. */ -static bool fill_data_into_slot(const Logger *log, struct RTPWorkBufferList *wkbl, const uint8_t slot_id, +static bool fill_data_into_slot(Tox *tox, struct RTPWorkBufferList *wkbl, const uint8_t slot_id, bool is_keyframe, const struct RTPHeader *header, const uint8_t *incoming_data, uint16_t incoming_data_length) { @@ -273,8 +283,8 @@ static bool fill_data_into_slot(const Logger *log, struct RTPWorkBufferList *wkb struct RTPMessage *msg = (struct RTPMessage *)calloc(1, sizeof(struct RTPMessage) + header->data_length_full); if (msg == nullptr) { - LOGGER_ERROR(log, "Out of memory while trying to allocate for frame of size %u", - (unsigned)header->data_length_full); + LOGGER_API_ERROR(tox, "Out of memory while trying to allocate for frame of size %u", + (unsigned)header->data_length_full); // Out of memory: throw away the incoming data. return false; } @@ -313,7 +323,7 @@ static bool fill_data_into_slot(const Logger *log, struct RTPWorkBufferList *wkb return slot->received_len == header->data_length_full; } -static void update_bwc_values(const Logger *log, RTPSession *session, const struct RTPMessage *msg) +static void update_bwc_values(RTPSession *session, const struct RTPMessage *msg) { if (session->first_packets_counter < DISMISS_FIRST_LOST_VIDEO_PACKET_COUNT) { ++session->first_packets_counter; @@ -323,12 +333,25 @@ static void update_bwc_values(const Logger *log, RTPSession *session, const stru bwc_add_recv(session->bwc, data_length_full); if (received_length_full < data_length_full) { - LOGGER_DEBUG(log, "BWC: full length=%u received length=%d", data_length_full, received_length_full); + LOGGER_API_DEBUG(session->tox, "BWC: full length=%u received length=%d", data_length_full, received_length_full); bwc_add_lost(session->bwc, (data_length_full - received_length_full)); } } } +static Mono_Time *rtp_get_mono_time_from_rtpsession(RTPSession *session) +{ + if (!session) { + return nullptr; + } + + if (!session->toxav) { + return nullptr; + } + + return toxav_get_av_mono_time(session->toxav); +} + /** * Handle a single RTP video packet. * @@ -346,7 +369,6 @@ static void update_bwc_values(const Logger *log, RTPSession *session, const stru * payload. * @param incoming_data_length The packet length *not* including header, i.e. * this is the actual payload length. - * @param log A logger. * * @return -1 on error, 0 on success. */ @@ -357,22 +379,16 @@ static int handle_video_packet(RTPSession *session, const struct RTPHeader *head // but this value is the complete assembled frame size. const uint32_t full_frame_length = header->data_length_full; - // Current offset in the frame. If this is the first packet of a multipart - // frame or it's not a multipart frame, then this value is 0. - const uint32_t offset = header->offset_full; // without header - // The sender tells us whether this is a key frame. const bool is_keyframe = (header->flags & RTP_KEY_FRAME) != 0; - LOGGER_DEBUG(log, "-- handle_video_packet -- full lens=%u len=%u offset=%u is_keyframe=%s", - (unsigned)incoming_data_length, (unsigned)full_frame_length, (unsigned)offset, is_keyframe ? "K" : "."); - LOGGER_DEBUG(log, "wkbl->next_free_entry:003=%d", session->work_buffer_list->next_free_entry); + LOGGER_API_DEBUG(session->tox, "wkbl->next_free_entry:003=%d", session->work_buffer_list->next_free_entry); const bool is_multipart = full_frame_length != incoming_data_length; /* The message was sent in single part */ - int8_t slot_id = get_slot(log, session->work_buffer_list, is_keyframe, header, is_multipart); - LOGGER_DEBUG(log, "slot num=%d", slot_id); + int8_t slot_id = get_slot(session->tox, session->work_buffer_list, is_keyframe, header, is_multipart); + LOGGER_API_DEBUG(session->tox, "slot num=%d", slot_id); // get_slot told us to drop the packet, so we ignore it. if (slot_id == GET_SLOT_RESULT_DROP_INCOMING) { @@ -381,25 +397,26 @@ static int handle_video_packet(RTPSession *session, const struct RTPHeader *head // get_slot said there is no free slot. if (slot_id == GET_SLOT_RESULT_DROP_OLDEST_SLOT) { - LOGGER_DEBUG(log, "there was no free slot, so we process the oldest frame"); + LOGGER_API_DEBUG(session->tox, "there was no free slot, so we process the oldest frame"); // We now own the frame. - struct RTPMessage *m_new = process_frame(log, session->work_buffer_list, 0); + struct RTPMessage *m_new = process_frame(session->tox, session->work_buffer_list, 0); // The process_frame function returns NULL if there is no slot 0, i.e. // the work buffer list is completely empty. It can't be empty, because // get_slot just told us it's full, so process_frame must return non-null. assert(m_new != nullptr); - LOGGER_DEBUG(log, "-- handle_video_packet -- CALLBACK-001a b0=%d b1=%d", (int)m_new->data[0], (int)m_new->data[1]); - update_bwc_values(log, session, m_new); + LOGGER_API_DEBUG(session->tox, "-- handle_video_packet -- CALLBACK-001a b0=%d b1=%d", (int)m_new->data[0], + (int)m_new->data[1]); + update_bwc_values(session, m_new); // Pass ownership of m_new to the callback. - session->mcb(session->m->mono_time, session->cs, m_new); + session->mcb(rtp_get_mono_time_from_rtpsession(session), session->cs, m_new); // Now we no longer own m_new. m_new = nullptr; // Now we must have a free slot, so we either get that slot, i.e. >= 0, // or get told to drop the incoming packet if it's too old. - slot_id = get_slot(log, session->work_buffer_list, is_keyframe, header, /* is_multipart */false); + slot_id = get_slot(session->tox, session->work_buffer_list, is_keyframe, header, /* is_multipart */false); if (slot_id == GET_SLOT_RESULT_DROP_INCOMING) { // The incoming frame is too old, so we drop it. @@ -410,11 +427,11 @@ static int handle_video_packet(RTPSession *session, const struct RTPHeader *head // We must have a valid slot here. assert(slot_id >= 0); - LOGGER_DEBUG(log, "fill_data_into_slot.1"); + LOGGER_API_DEBUG(session->tox, "fill_data_into_slot.1"); // fill in this part into the slot buffer at the correct offset if (!fill_data_into_slot( - log, + session->tox, session->work_buffer_list, slot_id, is_keyframe, @@ -425,12 +442,13 @@ static int handle_video_packet(RTPSession *session, const struct RTPHeader *head return -1; } - struct RTPMessage *m_new = process_frame(log, session->work_buffer_list, slot_id); + struct RTPMessage *m_new = process_frame(session->tox, session->work_buffer_list, slot_id); if (m_new) { - LOGGER_DEBUG(log, "-- handle_video_packet -- CALLBACK-003a b0=%d b1=%d", (int)m_new->data[0], (int)m_new->data[1]); - update_bwc_values(log, session, m_new); - session->mcb(session->m->mono_time, session->cs, m_new); + LOGGER_API_DEBUG(session->tox, "-- handle_video_packet -- CALLBACK-003a b0=%d b1=%d", (int)m_new->data[0], + (int)m_new->data[1]); + update_bwc_values(session, m_new); + session->mcb(rtp_get_mono_time_from_rtpsession(session), session->cs, m_new); m_new = nullptr; } @@ -439,15 +457,40 @@ static int handle_video_packet(RTPSession *session, const struct RTPHeader *head } /** - * @return -1 on error, 0 on success. + * receive custom lossypackets and process them. they can be incoming audio or video packets */ -static int handle_rtp_packet(Messenger *m, uint32_t friendnumber, const uint8_t *data, uint16_t length, void *object) +void handle_rtp_packet(Tox *tox, uint32_t friendnumber, const uint8_t *data, size_t length2, void *dummy) { - RTPSession *session = (RTPSession *)object; + // TODO(Zoff): is this ok? + uint16_t length = (uint16_t)length2; - if (!session || length < RTP_HEADER_SIZE + 1) { - LOGGER_WARNING(m->log, "No session or invalid length of received buffer!"); - return -1; + if (length < RTP_HEADER_SIZE + 1) { + LOGGER_API_WARNING(tox, "Invalid length of received buffer!"); + return; + } + + ToxAV *toxav = (ToxAV *)tox_get_av_object(tox); + + if (!toxav) { + return; + } + + ToxAVCall *call = (ToxAVCall *)call_get(toxav, friendnumber); + + if (!call) { + return; + } + + RTPSession *session = rtp_session_get(call, data[0]); + + if (!session) { + LOGGER_API_WARNING(tox, "No session!"); + return; + } + + if (!session->rtp_receive_active) { + LOGGER_API_WARNING(tox, "receiving not allowed!"); + return; } // Get the packet type. @@ -460,35 +503,36 @@ static int handle_rtp_packet(Messenger *m, uint32_t friendnumber, const uint8_t rtp_header_unpack(data, &header); if (header.pt != packet_type % 128) { - LOGGER_WARNING(m->log, "RTPHeader packet type and Tox protocol packet type did not agree: %d != %d", - header.pt, packet_type % 128); - return -1; + LOGGER_API_WARNING(tox, "RTPHeader packet type and Tox protocol packet type did not agree: %d != %d", + header.pt, packet_type % 128); + return; } if (header.pt != session->payload_type % 128) { - LOGGER_WARNING(m->log, "RTPHeader packet type does not match this session's payload type: %d != %d", - header.pt, session->payload_type % 128); - return -1; + LOGGER_API_WARNING(tox, "RTPHeader packet type does not match this session's payload type: %d != %d", + header.pt, session->payload_type % 128); + return; } if (header.flags & RTP_LARGE_FRAME && header.offset_full >= header.data_length_full) { - LOGGER_ERROR(m->log, "Invalid video packet: frame offset (%u) >= full frame length (%u)", - (unsigned)header.offset_full, (unsigned)header.data_length_full); - return -1; + LOGGER_API_ERROR(tox, "Invalid video packet: frame offset (%u) >= full frame length (%u)", + (unsigned)header.offset_full, (unsigned)header.data_length_full); + return; } if (header.offset_lower >= header.data_length_lower) { - LOGGER_ERROR(m->log, "Invalid old protocol video packet: frame offset (%u) >= full frame length (%u)", - (unsigned)header.offset_lower, (unsigned)header.data_length_lower); - return -1; + LOGGER_API_ERROR(tox, "Invalid old protocol video packet: frame offset (%u) >= full frame length (%u)", + (unsigned)header.offset_lower, (unsigned)header.data_length_lower); + return; } - LOGGER_DEBUG(m->log, "header.pt %d, video %d", (uint8_t)header.pt, (RTP_TYPE_VIDEO % 128)); + LOGGER_API_DEBUG(tox, "header.pt %d, video %d", (uint8_t)header.pt, (RTP_TYPE_VIDEO % 128)); // The sender uses the new large-frame capable protocol and is sending a // video packet. if ((header.flags & RTP_LARGE_FRAME) && header.pt == (RTP_TYPE_VIDEO % 128)) { - return handle_video_packet(session, &header, data + RTP_HEADER_SIZE, length - RTP_HEADER_SIZE, m->log); + handle_video_packet(session, &header, data + RTP_HEADER_SIZE, length - RTP_HEADER_SIZE, nullptr); + return; } // everything below here is for the old 16 bit protocol ------------------ @@ -503,15 +547,17 @@ static int handle_rtp_packet(Messenger *m, uint32_t friendnumber, const uint8_t /* Invoke processing of active multiparted message */ if (session->mp) { - session->mcb(session->m->mono_time, session->cs, session->mp); + session->mcb(rtp_get_mono_time_from_rtpsession(session), session->cs, session->mp); session->mp = nullptr; } /* The message came in the allowed time; */ - return session->mcb(session->m->mono_time, session->cs, new_message(&header, length - RTP_HEADER_SIZE, - data + RTP_HEADER_SIZE, length - RTP_HEADER_SIZE)); + session->mp = new_message(tox, &header, length - RTP_HEADER_SIZE, data + RTP_HEADER_SIZE, length - RTP_HEADER_SIZE); + session->mcb(rtp_get_mono_time_from_rtpsession(session), session->cs, session->mp); + session->mp = nullptr; + return; } /* The message is sent in multiple parts */ @@ -534,7 +580,7 @@ static int handle_rtp_packet(Messenger *m, uint32_t friendnumber, const uint8_t /* There happened to be some corruption on the stream; * continue wihtout this part */ - return 0; + return; } memcpy(session->mp->data + header.offset_lower, data + RTP_HEADER_SIZE, @@ -546,7 +592,7 @@ static int handle_rtp_packet(Messenger *m, uint32_t friendnumber, const uint8_t /* Received a full message; now push it for the further * processing. */ - session->mcb(session->m->mono_time, session->cs, session->mp); + session->mcb(rtp_get_mono_time_from_rtpsession(session), session->cs, session->mp); session->mp = nullptr; } } else { @@ -555,17 +601,17 @@ static int handle_rtp_packet(Messenger *m, uint32_t friendnumber, const uint8_t /* The received message part is from the old message; * discard it. */ - return 0; + return; } /* Push the previous message for processing */ - session->mcb(session->m->mono_time, session->cs, session->mp); + session->mcb(rtp_get_mono_time_from_rtpsession(session), session->cs, session->mp); session->mp = nullptr; goto NEW_MULTIPARTED; } } else { - /* In this case threat the message as if it was received in order + /* In this case treat the message as if it was received in order */ /* This is also a point for new multiparted messages */ NEW_MULTIPARTED: @@ -577,11 +623,11 @@ static int handle_rtp_packet(Messenger *m, uint32_t friendnumber, const uint8_t /* Store message. */ - session->mp = new_message(&header, header.data_length_lower, data + RTP_HEADER_SIZE, length - RTP_HEADER_SIZE); + session->mp = new_message(tox, &header, header.data_length_lower, data + RTP_HEADER_SIZE, length - RTP_HEADER_SIZE); memmove(session->mp->data + header.offset_lower, session->mp->data, session->mp->len); } - return 0; + return; } size_t rtp_header_pack(uint8_t *const rdata, const struct RTPHeader *header) @@ -643,24 +689,23 @@ size_t rtp_header_unpack(const uint8_t *data, struct RTPHeader *header) return p - data; } -RTPSession *rtp_new(int payload_type, Messenger *m, Tox *tox, uint32_t friendnumber, +RTPSession *rtp_new(int payload_type, Tox *tox, ToxAV *toxav, uint32_t friendnumber, BWController *bwc, void *cs, rtp_m_cb *mcb) { assert(mcb != nullptr); assert(cs != nullptr); - assert(m != nullptr); RTPSession *session = (RTPSession *)calloc(1, sizeof(RTPSession)); if (!session) { - LOGGER_WARNING(m->log, "Alloc failed! Program might misbehave!"); + LOGGER_API_WARNING(tox, "Alloc failed! Program might misbehave!"); return nullptr; } session->work_buffer_list = (struct RTPWorkBufferList *)calloc(1, sizeof(struct RTPWorkBufferList)); if (session->work_buffer_list == nullptr) { - LOGGER_ERROR(m->log, "out of memory while allocating work buffer list"); + LOGGER_API_ERROR(tox, "out of memory while allocating work buffer list"); free(session); return nullptr; } @@ -668,11 +713,13 @@ RTPSession *rtp_new(int payload_type, Messenger *m, Tox *tox, uint32_t friendnum // First entry is free. session->work_buffer_list->next_free_entry = 0; - session->ssrc = payload_type == RTP_TYPE_VIDEO ? 0 : random_u32(); + session->ssrc = payload_type == RTP_TYPE_VIDEO ? 0 : random_u32(); // Zoff: what is this?? session->payload_type = payload_type; - session->m = m; + // session->m = m; session->tox = tox; + session->toxav = toxav; session->friend_number = friendnumber; + session->rtp_receive_active = true; /* default: true */ // set NULL just in case session->mp = nullptr; @@ -683,58 +730,49 @@ RTPSession *rtp_new(int payload_type, Messenger *m, Tox *tox, uint32_t friendnum session->cs = cs; session->mcb = mcb; - if (-1 == rtp_allow_receiving(session)) { - LOGGER_WARNING(m->log, "Failed to start rtp receiving mode"); - free(session->work_buffer_list); - free(session); - return nullptr; - } - return session; } -void rtp_kill(RTPSession *session) +void rtp_kill(Tox *tox, RTPSession *session) { if (!session) { return; } - LOGGER_DEBUG(session->m->log, "Terminated RTP session: %p", (void *)session); - rtp_stop_receiving(session); - - LOGGER_DEBUG(session->m->log, "Terminated RTP session V3 work_buffer_list->next_free_entry: %d", - (int)session->work_buffer_list->next_free_entry); + LOGGER_API_DEBUG(session->tox, "Terminated RTP session: %p", (void *)session); + LOGGER_API_DEBUG(session->tox, "Terminated RTP session V3 work_buffer_list->next_free_entry: %d", + (int)session->work_buffer_list->next_free_entry); free(session->work_buffer_list); free(session); } -int rtp_allow_receiving(RTPSession *session) +void rtp_allow_receiving_mark(Tox *tox, RTPSession *session) { - if (session == nullptr) { - return -1; + if (session) { + session->rtp_receive_active = true; } - - if (m_callback_rtp_packet(session->m, session->friend_number, session->payload_type, - handle_rtp_packet, session) == -1) { - LOGGER_WARNING(session->m->log, "Failed to register rtp receive handler"); - return -1; - } - - LOGGER_DEBUG(session->m->log, "Started receiving on session: %p", (void *)session); - return 0; } -int rtp_stop_receiving(RTPSession *session) +void rtp_stop_receiving_mark(Tox *tox, RTPSession *session) { - if (session == nullptr) { - return -1; + if (session) { + session->rtp_receive_active = false; } +} - m_callback_rtp_packet(session->m, session->friend_number, session->payload_type, nullptr, nullptr); +void rtp_allow_receiving(Tox *tox) +{ + // register callback + tox_callback_friend_lossy_packet_per_pktid(tox, handle_rtp_packet, RTP_TYPE_AUDIO); + tox_callback_friend_lossy_packet_per_pktid(tox, handle_rtp_packet, RTP_TYPE_VIDEO); +} - LOGGER_DEBUG(session->m->log, "Stopped receiving on session: %p", (void *)session); - return 0; +void rtp_stop_receiving(Tox *tox) +{ + // UN-register callback + tox_callback_friend_lossy_packet_per_pktid(tox, nullptr, RTP_TYPE_AUDIO); + tox_callback_friend_lossy_packet_per_pktid(tox, nullptr, RTP_TYPE_VIDEO); } /** @@ -745,7 +783,6 @@ int rtp_send_data(RTPSession *session, const uint8_t *data, uint32_t length, bool is_keyframe, const Logger *log) { if (!session) { - LOGGER_ERROR(log, "No session!"); return -1; } @@ -765,7 +802,7 @@ int rtp_send_data(RTPSession *session, const uint8_t *data, uint32_t length, header.sequnum = session->sequnum; - header.timestamp = current_time_monotonic(session->m->mono_time); + header.timestamp = current_time_monotonic(rtp_get_mono_time_from_rtpsession(session)); header.ssrc = session->ssrc; @@ -807,8 +844,8 @@ int rtp_send_data(RTPSession *session, const uint8_t *data, uint32_t length, if (-1 == rtp_send_custom_lossy_packet(session->tox, session->friend_number, rdata, SIZEOF_VLA(rdata))) { const char *netstrerror = net_new_strerror(net_error()); - LOGGER_WARNING(session->m->log, "RTP send failed (len: %u)! std error: %s, net error: %s", - (unsigned)SIZEOF_VLA(rdata), strerror(errno), netstrerror); + LOGGER_API_WARNING(session->tox, "RTP send failed (len: %u)! std error: %s, net error: %s", + (unsigned)SIZEOF_VLA(rdata), strerror(errno), netstrerror); net_kill_strerror(netstrerror); } } else { @@ -826,8 +863,8 @@ int rtp_send_data(RTPSession *session, const uint8_t *data, uint32_t length, if (-1 == rtp_send_custom_lossy_packet(session->tox, session->friend_number, rdata, piece + RTP_HEADER_SIZE + 1)) { const char *netstrerror = net_new_strerror(net_error()); - LOGGER_WARNING(session->m->log, "RTP send failed (len: %d)! std error: %s, net error: %s", - piece + RTP_HEADER_SIZE + 1, strerror(errno), netstrerror); + LOGGER_API_WARNING(session->tox, "RTP send failed (len: %d)! std error: %s, net error: %s", + piece + RTP_HEADER_SIZE + 1, strerror(errno), netstrerror); net_kill_strerror(netstrerror); } @@ -846,8 +883,8 @@ int rtp_send_data(RTPSession *session, const uint8_t *data, uint32_t length, if (-1 == rtp_send_custom_lossy_packet(session->tox, session->friend_number, rdata, piece + RTP_HEADER_SIZE + 1)) { const char *netstrerror = net_new_strerror(net_error()); - LOGGER_WARNING(session->m->log, "RTP send failed (len: %d)! std error: %s, net error: %s", - piece + RTP_HEADER_SIZE + 1, strerror(errno), netstrerror); + LOGGER_API_WARNING(session->tox, "RTP send failed (len: %d)! std error: %s, net error: %s", + piece + RTP_HEADER_SIZE + 1, strerror(errno), netstrerror); net_kill_strerror(netstrerror); } } diff --git a/toxav/rtp.h b/toxav/rtp.h index be9e63f809..40af775c7e 100644 --- a/toxav/rtp.h +++ b/toxav/rtp.h @@ -7,7 +7,7 @@ #include "bwcontroller.h" -#include "../toxcore/Messenger.h" +#include "../toxcore/tox.h" #include "../toxcore/logger.h" #include @@ -16,11 +16,6 @@ extern "C" { #endif -#ifndef TOX_DEFINED -#define TOX_DEFINED -typedef struct Tox Tox; -#endif /* TOX_DEFINED */ - /** * RTPHeader serialised size in bytes. */ @@ -40,6 +35,11 @@ typedef enum RTP_Type { RTP_TYPE_VIDEO = 193, } RTP_Type; +#ifndef TOXAV_DEFINED +#define TOXAV_DEFINED +typedef struct ToxAV ToxAV; +#endif /* TOXAV_DEFINED */ + /** * A bit mask (up to 64 bits) specifying features of the current frame affecting * the behaviour of the decoder. @@ -163,15 +163,18 @@ typedef struct RTPSession { struct RTPMessage *mp; /* Expected parted message */ struct RTPWorkBufferList *work_buffer_list; uint8_t first_packets_counter; /* dismiss first few lost video packets */ - Messenger *m; Tox *tox; + ToxAV *toxav; uint32_t friend_number; + bool rtp_receive_active; BWController *bwc; void *cs; rtp_m_cb *mcb; } RTPSession; +void handle_rtp_packet(Tox *tox, uint32_t friendnumber, const uint8_t *data, size_t length, void *object); + /** * Serialise an RTPHeader to bytes to be sent over the network. * @@ -190,11 +193,14 @@ size_t rtp_header_pack(uint8_t *rdata, const struct RTPHeader *header); */ size_t rtp_header_unpack(const uint8_t *data, struct RTPHeader *header); -RTPSession *rtp_new(int payload_type, Messenger *m, Tox *tox, uint32_t friendnumber, +RTPSession *rtp_new(int payload_type, Tox *tox, ToxAV *toxav, uint32_t friendnumber, BWController *bwc, void *cs, rtp_m_cb *mcb); -void rtp_kill(RTPSession *session); -int rtp_allow_receiving(RTPSession *session); -int rtp_stop_receiving(RTPSession *session); +void rtp_kill(Tox *tox, RTPSession *session); +void rtp_allow_receiving_mark(Tox *tox, RTPSession *session); +void rtp_stop_receiving_mark(Tox *tox, RTPSession *session); +void rtp_allow_receiving(Tox *tox); +void rtp_stop_receiving(Tox *tox); + /** * Send a frame of audio or video data, chunked in \ref RTPMessage instances. * diff --git a/toxav/toxav.c b/toxav/toxav.c index 0ecf82590f..a1a71b1ac3 100644 --- a/toxav/toxav.c +++ b/toxav/toxav.c @@ -7,14 +7,17 @@ #endif /* HAVE_CONFIG_H */ #include "toxav.h" +#include "../toxcore/tox.h" +#include "../toxcore/tox_private.h" #include "msi.h" #include "rtp.h" -#include "../toxcore/Messenger.h" #include "../toxcore/logger.h" #include "../toxcore/mono_time.h" #include "../toxcore/util.h" +#include "../toxcore/network.h" +#include "../toxcore/net_crypto.h" #include #include @@ -35,7 +38,13 @@ VPX_DL_GOOD_QUALITY (1000000) deadline parameter analogous to VPx GOOD QUALITY VPX_DL_BEST_QUALITY (0) deadline parameter analogous to VPx BEST QUALITY mode. */ -typedef struct ToxAVCall_s { + +#ifndef TOXAV_CALL_DEFINED +#define TOXAV_CALL_DEFINED +typedef struct ToxAVCall ToxAVCall; +#endif /* TOXAV_CALL_DEFINED */ + +struct ToxAVCall { ToxAV *av; pthread_mutex_t mutex_audio[1]; @@ -60,13 +69,14 @@ typedef struct ToxAVCall_s { pthread_mutex_t toxav_call_mutex[1]; - struct ToxAVCall_s *prev; - struct ToxAVCall_s *next; -} ToxAVCall; + ToxAVCall *prev; + ToxAVCall *next; +}; + +#include "toxav_hacks.h" struct ToxAV { Tox *tox; - Messenger *m; MSISession *msi; /* Two-way storage: first is array of calls and second is list of calls with head and tail */ @@ -100,7 +110,8 @@ struct ToxAV { int32_t dmssa; /** Average decoding time in ms */ uint32_t interval; /** Calculated interval */ - Mono_Time *toxav_mono_time; /** ToxAV's own mono_time instance */ + + Mono_Time *toxav_mono_time; // ToxAV's own mono_time instance }; static void callback_bwc(BWController *bwc, uint32_t friend_number, float loss, void *user_data); @@ -115,10 +126,59 @@ static bool audio_bit_rate_invalid(uint32_t bit_rate); static bool video_bit_rate_invalid(uint32_t bit_rate); static bool invoke_call_state_callback(ToxAV *av, uint32_t friend_number, uint32_t state); static ToxAVCall *call_new(ToxAV *av, uint32_t friend_number, Toxav_Err_Call *error); -static ToxAVCall *call_get(ToxAV *av, uint32_t friend_number); static ToxAVCall *call_remove(ToxAVCall *call); static bool call_prepare_transmission(ToxAVCall *call); static void call_kill_transmission(ToxAVCall *call); +static int toxav_friend_exists(const Tox *tox, int32_t friendnumber); + +MSISession *tox_av_msi_get(ToxAV *av) +{ + if (!av) { + return nullptr; + } + + return av->msi; +} + +ToxAVCall *call_get(ToxAV *av, uint32_t friend_number) +{ + if (av == nullptr) { + return nullptr; + } + + /* Assumes mutex locked */ + if (av->calls == nullptr || av->calls_tail < friend_number) { + return nullptr; + } + + return av->calls[friend_number]; +} + +RTPSession *rtp_session_get(ToxAVCall *call, int payload_type) +{ + if (call == nullptr) { + return nullptr; + } + + if (payload_type == RTP_TYPE_VIDEO) { + return call->video_rtp; + } else { + return call->audio_rtp; + } + + return nullptr; +} + +BWController *bwc_controller_get(void *call) +{ + ToxAVCall *toxavcall = (ToxAVCall *)call; + + if (toxavcall == nullptr) { + return nullptr; + } + + return toxavcall->bwc; +} ToxAV *toxav_new(Tox *tox, Toxav_Err_New *error) { @@ -130,35 +190,25 @@ ToxAV *toxav_new(Tox *tox, Toxav_Err_New *error) goto RETURN; } - // TODO(iphydf): Don't rely on toxcore internals. - Messenger *m; - //!TOKSTYLE- - m = *(Messenger **)tox; - //!TOKSTYLE+ - - if (m->msi_packet) { - rc = TOXAV_ERR_NEW_MULTIPLE; - goto RETURN; - } - av = (ToxAV *)calloc(sizeof(ToxAV), 1); if (av == nullptr) { - LOGGER_WARNING(m->log, "Allocation failed!"); rc = TOXAV_ERR_NEW_MALLOC; goto RETURN; } if (create_recursive_mutex(av->mutex) != 0) { - LOGGER_WARNING(m->log, "Mutex creation failed!"); rc = TOXAV_ERR_NEW_MALLOC; goto RETURN; } av->tox = tox; - av->m = m; + av->msi = msi_new(av->tox); + + rtp_allow_receiving(av->tox); + bwc_allow_receiving(av->tox); + av->toxav_mono_time = mono_time_new(); - av->msi = msi_new(av->m); if (av->msi == nullptr) { pthread_mutex_destroy(av->mutex); @@ -169,6 +219,9 @@ ToxAV *toxav_new(Tox *tox, Toxav_Err_New *error) av->interval = 200; av->msi->av = av; + // save Tox object into toxcore + tox_set_av_object(av->tox, (void *)av); + msi_register_callback(av->msi, callback_invite, MSI_ON_INVITE); msi_register_callback(av->msi, callback_start, MSI_ON_START); msi_register_callback(av->msi, callback_end, MSI_ON_END); @@ -189,6 +242,7 @@ ToxAV *toxav_new(Tox *tox, Toxav_Err_New *error) return av; } + void toxav_kill(ToxAV *av) { if (av == nullptr) { @@ -197,8 +251,16 @@ void toxav_kill(ToxAV *av) pthread_mutex_lock(av->mutex); + // unregister callbacks + for (uint8_t i = PACKET_ID_RANGE_LOSSY_AV_START; i <= PACKET_ID_RANGE_LOSSY_AV_END; ++i) { + tox_callback_friend_lossy_packet_per_pktid(av->tox, nullptr, i); + } + + rtp_stop_receiving(av->tox); + bwc_stop_receiving(av->tox); + /* To avoid possible deadlocks */ - while (av->msi && msi_kill(av->msi, av->m->log) != 0) { + while (av->msi && msi_kill(av->tox, av->msi, nullptr) != 0) { pthread_mutex_unlock(av->mutex); pthread_mutex_lock(av->mutex); } @@ -221,15 +283,18 @@ void toxav_kill(ToxAV *av) free(av); } + Tox *toxav_get_tox(const ToxAV *av) { return av->tox; } + uint32_t toxav_iteration_interval(const ToxAV *av) { /* If no call is active interval is 200 */ return av->calls ? av->interval : 200; } + void toxav_iterate(ToxAV *av) { pthread_mutex_lock(av->mutex); @@ -249,6 +314,15 @@ void toxav_iterate(ToxAV *av) pthread_mutex_lock(i->toxav_call_mutex); pthread_mutex_unlock(av->mutex); + uint32_t fid = i->friend_number; + bool is_offline = check_peer_offline_status(av->tox, i->msi_call->session, fid); + + if (is_offline) { + pthread_mutex_unlock(i->toxav_call_mutex); + pthread_mutex_lock(av->mutex); + break; + } + ac_iterate(i->audio); vc_iterate(i->video); @@ -264,8 +338,6 @@ void toxav_iterate(ToxAV *av) pthread_mutex_unlock(i->video->queue_mutex); } - uint32_t fid = i->friend_number; - pthread_mutex_unlock(i->toxav_call_mutex); pthread_mutex_lock(av->mutex); @@ -287,6 +359,7 @@ void toxav_iterate(ToxAV *av) pthread_mutex_unlock(av->mutex); } + bool toxav_call(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, Toxav_Err_Call *error) { @@ -332,6 +405,7 @@ bool toxav_call(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, uint return rc == TOXAV_ERR_CALL_OK; } + void toxav_callback_call(ToxAV *av, toxav_call_cb *callback, void *user_data) { pthread_mutex_lock(av->mutex); @@ -339,6 +413,22 @@ void toxav_callback_call(ToxAV *av, toxav_call_cb *callback, void *user_data) av->ccb_user_data = user_data; pthread_mutex_unlock(av->mutex); } + +static int toxav_friend_exists(const Tox *tox, int32_t friendnumber) +{ + if (tox) { + bool res = tox_friend_exists(tox, friendnumber); + + if (res) { + return 1; + } else { + return 0; + } + } + + return 0; +} + bool toxav_answer(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, Toxav_Err_Answer *error) { @@ -347,7 +437,7 @@ bool toxav_answer(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, ui Toxav_Err_Answer rc = TOXAV_ERR_ANSWER_OK; ToxAVCall *call; - if (m_friend_exists(av->m, friend_number) == 0) { + if (toxav_friend_exists(av->tox, friend_number) == 0) { rc = TOXAV_ERR_ANSWER_FRIEND_NOT_FOUND; goto RETURN; } @@ -392,6 +482,7 @@ bool toxav_answer(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, ui return rc == TOXAV_ERR_ANSWER_OK; } + void toxav_callback_call_state(ToxAV *av, toxav_call_state_cb *callback, void *user_data) { pthread_mutex_lock(av->mutex); @@ -399,13 +490,14 @@ void toxav_callback_call_state(ToxAV *av, toxav_call_state_cb *callback, void *u av->scb_user_data = user_data; pthread_mutex_unlock(av->mutex); } + bool toxav_call_control(ToxAV *av, uint32_t friend_number, Toxav_Call_Control control, Toxav_Err_Call_Control *error) { pthread_mutex_lock(av->mutex); Toxav_Err_Call_Control rc = TOXAV_ERR_CALL_CONTROL_OK; ToxAVCall *call; - if (m_friend_exists(av->m, friend_number) == 0) { + if (toxav_friend_exists(av->tox, friend_number) == 0) { rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_FOUND; goto RETURN; } @@ -429,8 +521,8 @@ bool toxav_call_control(ToxAV *av, uint32_t friend_number, Toxav_Call_Control co goto RETURN; } - rtp_allow_receiving(call->audio_rtp); - rtp_allow_receiving(call->video_rtp); + rtp_allow_receiving_mark(av->tox, call->audio_rtp); + rtp_allow_receiving_mark(av->tox, call->video_rtp); } else { rc = TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION; goto RETURN; @@ -448,8 +540,8 @@ bool toxav_call_control(ToxAV *av, uint32_t friend_number, Toxav_Call_Control co goto RETURN; } - rtp_stop_receiving(call->audio_rtp); - rtp_stop_receiving(call->video_rtp); + rtp_stop_receiving_mark(av->tox, call->audio_rtp); + rtp_stop_receiving_mark(av->tox, call->video_rtp); } else { rc = TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION; goto RETURN; @@ -484,7 +576,7 @@ bool toxav_call_control(ToxAV *av, uint32_t friend_number, Toxav_Call_Control co goto RETURN; } - rtp_stop_receiving(call->audio_rtp); + rtp_stop_receiving_mark(av->tox, call->audio_rtp); } else { rc = TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION; goto RETURN; @@ -500,7 +592,7 @@ bool toxav_call_control(ToxAV *av, uint32_t friend_number, Toxav_Call_Control co goto RETURN; } - rtp_allow_receiving(call->audio_rtp); + rtp_allow_receiving_mark(av->tox, call->audio_rtp); } else { rc = TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION; goto RETURN; @@ -516,7 +608,7 @@ bool toxav_call_control(ToxAV *av, uint32_t friend_number, Toxav_Call_Control co goto RETURN; } - rtp_stop_receiving(call->video_rtp); + rtp_stop_receiving_mark(av->tox, call->video_rtp); } else { rc = TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION; goto RETURN; @@ -532,7 +624,7 @@ bool toxav_call_control(ToxAV *av, uint32_t friend_number, Toxav_Call_Control co goto RETURN; } - rtp_allow_receiving(call->video_rtp); + rtp_allow_receiving_mark(av->tox, call->video_rtp); } else { rc = TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION; goto RETURN; @@ -550,13 +642,14 @@ bool toxav_call_control(ToxAV *av, uint32_t friend_number, Toxav_Call_Control co return rc == TOXAV_ERR_CALL_CONTROL_OK; } + bool toxav_audio_set_bit_rate(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, Toxav_Err_Bit_Rate_Set *error) { Toxav_Err_Bit_Rate_Set rc = TOXAV_ERR_BIT_RATE_SET_OK; ToxAVCall *call; - if (m_friend_exists(av->m, friend_number) == 0) { + if (toxav_friend_exists(av->tox, friend_number) == 0) { rc = TOXAV_ERR_BIT_RATE_SET_FRIEND_NOT_FOUND; goto RETURN; } @@ -575,12 +668,12 @@ bool toxav_audio_set_bit_rate(ToxAV *av, uint32_t friend_number, uint32_t audio_ goto RETURN; } - LOGGER_DEBUG(av->m->log, "Setting new audio bitrate to: %d", audio_bit_rate); + LOGGER_API_DEBUG(av->tox, "Setting new audio bitrate to: %d", audio_bit_rate); if (call->audio_bit_rate == audio_bit_rate) { - LOGGER_DEBUG(av->m->log, "Audio bitrate already set to: %d", audio_bit_rate); + LOGGER_API_DEBUG(av->tox, "Audio bitrate already set to: %d", audio_bit_rate); } else if (audio_bit_rate == 0) { - LOGGER_DEBUG(av->m->log, "Turned off audio sending"); + LOGGER_API_DEBUG(av->tox, "Turned off audio sending"); if (msi_change_capabilities(call->msi_call, call->msi_call-> self_capabilities ^ MSI_CAP_S_AUDIO) != 0) { @@ -595,7 +688,7 @@ bool toxav_audio_set_bit_rate(ToxAV *av, uint32_t friend_number, uint32_t audio_ pthread_mutex_lock(call->toxav_call_mutex); if (call->audio_bit_rate == 0) { - LOGGER_DEBUG(av->m->log, "Turned on audio sending"); + LOGGER_API_DEBUG(av->tox, "Turned on audio sending"); /* The audio has been turned off before this */ if (msi_change_capabilities(call->msi_call, call-> @@ -606,7 +699,7 @@ bool toxav_audio_set_bit_rate(ToxAV *av, uint32_t friend_number, uint32_t audio_ goto RETURN; } } else { - LOGGER_DEBUG(av->m->log, "Set new audio bit rate %d", audio_bit_rate); + LOGGER_API_DEBUG(av->tox, "Set new audio bit rate %d", audio_bit_rate); } call->audio_bit_rate = audio_bit_rate; @@ -622,13 +715,14 @@ bool toxav_audio_set_bit_rate(ToxAV *av, uint32_t friend_number, uint32_t audio_ return rc == TOXAV_ERR_BIT_RATE_SET_OK; } + bool toxav_video_set_bit_rate(ToxAV *av, uint32_t friend_number, uint32_t video_bit_rate, Toxav_Err_Bit_Rate_Set *error) { Toxav_Err_Bit_Rate_Set rc = TOXAV_ERR_BIT_RATE_SET_OK; ToxAVCall *call; - if (m_friend_exists(av->m, friend_number) == 0) { + if (toxav_friend_exists(av->tox, friend_number) == 0) { rc = TOXAV_ERR_BIT_RATE_SET_FRIEND_NOT_FOUND; goto RETURN; } @@ -647,12 +741,12 @@ bool toxav_video_set_bit_rate(ToxAV *av, uint32_t friend_number, uint32_t video_ goto RETURN; } - LOGGER_DEBUG(av->m->log, "Setting new video bitrate to: %d", video_bit_rate); + LOGGER_API_DEBUG(av->tox, "Setting new video bitrate to: %d", video_bit_rate); if (call->video_bit_rate == video_bit_rate) { - LOGGER_DEBUG(av->m->log, "Video bitrate already set to: %d", video_bit_rate); + LOGGER_API_DEBUG(av->tox, "Video bitrate already set to: %d", video_bit_rate); } else if (video_bit_rate == 0) { - LOGGER_DEBUG(av->m->log, "Turned off video sending"); + LOGGER_API_DEBUG(av->tox, "Turned off video sending"); /* Video sending is turned off; notify peer */ if (msi_change_capabilities(call->msi_call, call->msi_call-> @@ -667,7 +761,7 @@ bool toxav_video_set_bit_rate(ToxAV *av, uint32_t friend_number, uint32_t video_ pthread_mutex_lock(call->toxav_call_mutex); if (call->video_bit_rate == 0) { - LOGGER_DEBUG(av->m->log, "Turned on video sending"); + LOGGER_API_DEBUG(av->tox, "Turned on video sending"); /* The video has been turned off before this */ if (msi_change_capabilities(call->msi_call, call-> @@ -678,7 +772,7 @@ bool toxav_video_set_bit_rate(ToxAV *av, uint32_t friend_number, uint32_t video_ goto RETURN; } } else { - LOGGER_DEBUG(av->m->log, "Set new video bit rate %d", video_bit_rate); + LOGGER_API_DEBUG(av->tox, "Set new video bit rate %d", video_bit_rate); } call->video_bit_rate = video_bit_rate; @@ -694,6 +788,7 @@ bool toxav_video_set_bit_rate(ToxAV *av, uint32_t friend_number, uint32_t video_ return rc == TOXAV_ERR_BIT_RATE_SET_OK; } + void toxav_callback_audio_bit_rate(ToxAV *av, toxav_audio_bit_rate_cb *callback, void *user_data) { pthread_mutex_lock(av->mutex); @@ -701,6 +796,7 @@ void toxav_callback_audio_bit_rate(ToxAV *av, toxav_audio_bit_rate_cb *callback, av->abcb_user_data = user_data; pthread_mutex_unlock(av->mutex); } + void toxav_callback_video_bit_rate(ToxAV *av, toxav_video_bit_rate_cb *callback, void *user_data) { pthread_mutex_lock(av->mutex); @@ -708,13 +804,14 @@ void toxav_callback_video_bit_rate(ToxAV *av, toxav_video_bit_rate_cb *callback, av->vbcb_user_data = user_data; pthread_mutex_unlock(av->mutex); } + bool toxav_audio_send_frame(ToxAV *av, uint32_t friend_number, const int16_t *pcm, size_t sample_count, uint8_t channels, uint32_t sampling_rate, Toxav_Err_Send_Frame *error) { Toxav_Err_Send_Frame rc = TOXAV_ERR_SEND_FRAME_OK; ToxAVCall *call; - if (m_friend_exists(av->m, friend_number) == 0) { + if (toxav_friend_exists(av->tox, friend_number) == 0) { rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_FOUND; goto RETURN; } @@ -770,14 +867,14 @@ bool toxav_audio_send_frame(ToxAV *av, uint32_t friend_number, const int16_t *pc dest + sizeof(sampling_rate), SIZEOF_VLA(dest) - sizeof(sampling_rate)); if (vrc < 0) { - LOGGER_WARNING(av->m->log, "Failed to encode frame %s", opus_strerror(vrc)); + LOGGER_API_WARNING(av->tox, "Failed to encode frame %s", opus_strerror(vrc)); pthread_mutex_unlock(call->mutex_audio); rc = TOXAV_ERR_SEND_FRAME_INVALID; goto RETURN; } - if (rtp_send_data(call->audio_rtp, dest, vrc + sizeof(sampling_rate), false, av->m->log) != 0) { - LOGGER_WARNING(av->m->log, "Failed to send audio packet"); + if (rtp_send_data(call->audio_rtp, dest, vrc + sizeof(sampling_rate), false, nullptr) != 0) { + LOGGER_API_WARNING(av->tox, "Failed to send audio packet"); rc = TOXAV_ERR_SEND_FRAME_RTP_FAILED; } } @@ -793,7 +890,7 @@ bool toxav_audio_send_frame(ToxAV *av, uint32_t friend_number, const int16_t *pc return rc == TOXAV_ERR_SEND_FRAME_OK; } -static Toxav_Err_Send_Frame send_frames(const Logger *log, ToxAVCall *call) +static Toxav_Err_Send_Frame send_frames(ToxAV *av, ToxAVCall *call) { vpx_codec_iter_t iter = nullptr; @@ -815,15 +912,10 @@ static Toxav_Err_Send_Frame send_frames(const Logger *log, ToxAVCall *call) (const uint8_t *)pkt->data.frame.buf, frame_length_in_bytes, is_keyframe, - log); - - LOGGER_DEBUG(log, "+ _sending_FRAME_TYPE_==%s bytes=%d frame_len=%d", is_keyframe ? "K" : ".", - (int)pkt->data.frame.sz, (int)frame_length_in_bytes); - const uint8_t *const buf = (const uint8_t *)pkt->data.frame.buf; - LOGGER_DEBUG(log, "+ _sending_FRAME_ b0=%d b1=%d", buf[0], buf[1]); + nullptr); if (res < 0) { - LOGGER_WARNING(log, "Could not send video frame: %s", strerror(errno)); + LOGGER_API_WARNING(av->tox, "Could not send video frame: %s", strerror(errno)); return TOXAV_ERR_SEND_FRAME_RTP_FAILED; } } @@ -839,7 +931,7 @@ bool toxav_video_send_frame(ToxAV *av, uint32_t friend_number, uint16_t width, u int vpx_encode_flags = 0; - if (m_friend_exists(av->m, friend_number) == 0) { + if (toxav_friend_exists(av->tox, friend_number) == 0) { rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_FOUND; goto RETURN; } @@ -883,13 +975,13 @@ bool toxav_video_send_frame(ToxAV *av, uint32_t friend_number, uint16_t width, u if (call->video_rtp->ssrc < VIDEO_SEND_X_KEYFRAMES_FIRST) { // Key frame flag for first frames vpx_encode_flags = VPX_EFLAG_FORCE_KF; - LOGGER_INFO(av->m->log, "I_FRAME_FLAG:%d only-i-frame mode", call->video_rtp->ssrc); + LOGGER_API_INFO(av->tox, "I_FRAME_FLAG:%d only-i-frame mode", call->video_rtp->ssrc); ++call->video_rtp->ssrc; } else if (call->video_rtp->ssrc == VIDEO_SEND_X_KEYFRAMES_FIRST) { // normal keyframe placement vpx_encode_flags = 0; - LOGGER_INFO(av->m->log, "I_FRAME_FLAG:%d normal mode", call->video_rtp->ssrc); + LOGGER_API_INFO(av->tox, "I_FRAME_FLAG:%d normal mode", call->video_rtp->ssrc); ++call->video_rtp->ssrc; } @@ -918,7 +1010,7 @@ bool toxav_video_send_frame(ToxAV *av, uint32_t friend_number, uint16_t width, u if (vrc != VPX_CODEC_OK) { pthread_mutex_unlock(call->mutex_video); - LOGGER_ERROR(av->m->log, "Could not encode video frame: %s", vpx_codec_err_to_string(vrc)); + LOGGER_API_ERROR(av->tox, "Could not encode video frame: %s", vpx_codec_err_to_string(vrc)); rc = TOXAV_ERR_SEND_FRAME_INVALID; goto RETURN; } @@ -926,7 +1018,7 @@ bool toxav_video_send_frame(ToxAV *av, uint32_t friend_number, uint16_t width, u ++call->video->frame_counter; - rc = send_frames(av->m->log, call); + rc = send_frames(av, call); pthread_mutex_unlock(call->mutex_video); @@ -972,7 +1064,7 @@ static void callback_bwc(BWController *bwc, uint32_t friend_number, float loss, ToxAVCall *call = (ToxAVCall *)user_data; assert(call); - LOGGER_DEBUG(call->av->m->log, "Reported loss of %f%%", (double)loss * 100); + LOGGER_API_DEBUG(call->av->tox, "Reported loss of %f%%", (double)loss * 100); /* if less than 10% data loss we do nothing! */ if (loss < 0.1f) { @@ -984,7 +1076,7 @@ static void callback_bwc(BWController *bwc, uint32_t friend_number, float loss, if (call->video_bit_rate) { if (!call->av->vbcb) { pthread_mutex_unlock(call->av->mutex); - LOGGER_WARNING(call->av->m->log, "No callback to report loss on"); + LOGGER_API_WARNING(call->av->tox, "No callback to report loss on"); return; } @@ -994,7 +1086,7 @@ static void callback_bwc(BWController *bwc, uint32_t friend_number, float loss, } else if (call->audio_bit_rate) { if (!call->av->abcb) { pthread_mutex_unlock(call->av->mutex); - LOGGER_WARNING(call->av->m->log, "No callback to report loss on"); + LOGGER_API_WARNING(call->av->tox, "No callback to report loss on"); return; } @@ -1005,6 +1097,7 @@ static void callback_bwc(BWController *bwc, uint32_t friend_number, float loss, pthread_mutex_unlock(call->av->mutex); } + static int callback_invite(void *toxav_inst, MSICall *call) { ToxAV *toxav = (ToxAV *)toxav_inst; @@ -1013,7 +1106,7 @@ static int callback_invite(void *toxav_inst, MSICall *call) ToxAVCall *av_call = call_new(toxav, call->friend_number, nullptr); if (av_call == nullptr) { - LOGGER_WARNING(toxav->m->log, "Failed to initialize call..."); + LOGGER_API_WARNING(toxav->tox, "Failed to initialize call..."); pthread_mutex_unlock(toxav->mutex); return -1; } @@ -1033,6 +1126,7 @@ static int callback_invite(void *toxav_inst, MSICall *call) pthread_mutex_unlock(toxav->mutex); return 0; } + static int callback_start(void *toxav_inst, MSICall *call) { ToxAV *toxav = (ToxAV *)toxav_inst; @@ -1061,6 +1155,7 @@ static int callback_start(void *toxav_inst, MSICall *call) pthread_mutex_unlock(toxav->mutex); return 0; } + static int callback_end(void *toxav_inst, MSICall *call) { ToxAV *toxav = (ToxAV *)toxav_inst; @@ -1076,6 +1171,7 @@ static int callback_end(void *toxav_inst, MSICall *call) pthread_mutex_unlock(toxav->mutex); return 0; } + static int callback_error(void *toxav_inst, MSICall *call) { ToxAV *toxav = (ToxAV *)toxav_inst; @@ -1091,21 +1187,22 @@ static int callback_error(void *toxav_inst, MSICall *call) pthread_mutex_unlock(toxav->mutex); return 0; } + static int callback_capabilites(void *toxav_inst, MSICall *call) { ToxAV *toxav = (ToxAV *)toxav_inst; pthread_mutex_lock(toxav->mutex); if (call->peer_capabilities & MSI_CAP_S_AUDIO) { - rtp_allow_receiving(call->av_call->audio_rtp); + rtp_allow_receiving_mark(toxav->tox, call->av_call->audio_rtp); } else { - rtp_stop_receiving(call->av_call->audio_rtp); + rtp_stop_receiving_mark(toxav->tox, call->av_call->audio_rtp); } if (call->peer_capabilities & MSI_CAP_S_VIDEO) { - rtp_allow_receiving(call->av_call->video_rtp); + rtp_allow_receiving_mark(toxav->tox, call->av_call->video_rtp); } else { - rtp_stop_receiving(call->av_call->video_rtp); + rtp_stop_receiving_mark(toxav->tox, call->av_call->video_rtp); } invoke_call_state_callback(toxav, call->friend_number, call->peer_capabilities); @@ -1113,6 +1210,7 @@ static int callback_capabilites(void *toxav_inst, MSICall *call) pthread_mutex_unlock(toxav->mutex); return 0; } + static bool audio_bit_rate_invalid(uint32_t bit_rate) { /* Opus RFC 6716 section-2.1.1 dictates the following: @@ -1120,6 +1218,7 @@ static bool audio_bit_rate_invalid(uint32_t bit_rate) */ return bit_rate < 6 || bit_rate > 510; } + static bool video_bit_rate_invalid(uint32_t bit_rate) { /* https://www.webmproject.org/docs/webm-sdk/structvpx__codec__enc__cfg.html shows the following: @@ -1131,6 +1230,7 @@ static bool video_bit_rate_invalid(uint32_t bit_rate) */ return bit_rate > UINT_MAX; } + static bool invoke_call_state_callback(ToxAV *av, uint32_t friend_number, uint32_t state) { if (av->scb) { @@ -1148,12 +1248,17 @@ static ToxAVCall *call_new(ToxAV *av, uint32_t friend_number, Toxav_Err_Call *er Toxav_Err_Call rc = TOXAV_ERR_CALL_OK; ToxAVCall *call = nullptr; - if (m_friend_exists(av->m, friend_number) == 0) { + Tox_Err_Friend_Query f_con_query_error; + Tox_Connection f_conn_status = TOX_CONNECTION_NONE; + + if (toxav_friend_exists(av->tox, friend_number) == 0) { rc = TOXAV_ERR_CALL_FRIEND_NOT_FOUND; goto RETURN; } - if (m_get_friend_connectionstatus(av->m, friend_number) < 1) { + f_conn_status = tox_friend_get_connection_status(av->tox, friend_number, &f_con_query_error); + + if (f_conn_status == TOX_CONNECTION_NONE) { rc = TOXAV_ERR_CALL_FRIEND_NOT_CONNECTED; goto RETURN; } @@ -1232,16 +1337,6 @@ static ToxAVCall *call_new(ToxAV *av, uint32_t friend_number, Toxav_Err_Call *er return call; } -static ToxAVCall *call_get(ToxAV *av, uint32_t friend_number) -{ - /* Assumes mutex locked */ - if (av->calls == nullptr || av->calls_tail < friend_number) { - return nullptr; - } - - return av->calls[friend_number]; -} - static ToxAVCall *call_remove(ToxAVCall *call) { if (call == nullptr) { @@ -1308,7 +1403,7 @@ static bool call_prepare_transmission(ToxAVCall *call) } if (call->active) { - LOGGER_WARNING(av->m->log, "Call already active!"); + LOGGER_API_WARNING(av->tox, "Call already active!"); return true; } @@ -1321,37 +1416,37 @@ static bool call_prepare_transmission(ToxAVCall *call) } /* Prepare bwc */ - call->bwc = bwc_new(av->m, av->tox, call->friend_number, callback_bwc, call, av->toxav_mono_time); + call->bwc = bwc_new(av->tox, call->friend_number, callback_bwc, call, av->toxav_mono_time); { /* Prepare audio */ - call->audio = ac_new(av->toxav_mono_time, av->m->log, av, call->friend_number, av->acb, av->acb_user_data); + call->audio = ac_new(av->toxav_mono_time, av->tox, av, call->friend_number, av->acb, av->acb_user_data); if (!call->audio) { - LOGGER_ERROR(av->m->log, "Failed to create audio codec session"); + LOGGER_API_ERROR(av->tox, "Failed to create audio codec session"); goto FAILURE; } - call->audio_rtp = rtp_new(RTP_TYPE_AUDIO, av->m, av->tox, call->friend_number, call->bwc, + call->audio_rtp = rtp_new(RTP_TYPE_AUDIO, av->tox, av, call->friend_number, call->bwc, call->audio, ac_queue_message); if (!call->audio_rtp) { - LOGGER_ERROR(av->m->log, "Failed to create audio rtp session"); + LOGGER_API_ERROR(av->tox, "Failed to create audio rtp session"); goto FAILURE; } } { /* Prepare video */ - call->video = vc_new(av->toxav_mono_time, av->m->log, av, call->friend_number, av->vcb, av->vcb_user_data); + call->video = vc_new(av->toxav_mono_time, av->tox, av, call->friend_number, av->vcb, av->vcb_user_data); if (!call->video) { - LOGGER_ERROR(av->m->log, "Failed to create video codec session"); + LOGGER_API_ERROR(av->tox, "Failed to create video codec session"); goto FAILURE; } - call->video_rtp = rtp_new(RTP_TYPE_VIDEO, av->m, av->tox, call->friend_number, call->bwc, + call->video_rtp = rtp_new(RTP_TYPE_VIDEO, av->tox, av, call->friend_number, call->bwc, call->video, vc_queue_message); if (!call->video_rtp) { - LOGGER_ERROR(av->m->log, "Failed to create video rtp session"); + LOGGER_API_ERROR(av->tox, "Failed to create video rtp session"); goto FAILURE; } } @@ -1361,11 +1456,11 @@ static bool call_prepare_transmission(ToxAVCall *call) FAILURE: bwc_kill(call->bwc); - rtp_kill(call->audio_rtp); + rtp_kill(av->tox, call->audio_rtp); ac_kill(call->audio); call->audio_rtp = nullptr; call->audio = nullptr; - rtp_kill(call->video_rtp); + rtp_kill(av->tox, call->video_rtp); vc_kill(call->video); call->video_rtp = nullptr; call->video = nullptr; @@ -1392,12 +1487,14 @@ static void call_kill_transmission(ToxAVCall *call) bwc_kill(call->bwc); - rtp_kill(call->audio_rtp); + ToxAV *av = call->av; + + rtp_kill(av->tox, call->audio_rtp); ac_kill(call->audio); call->audio_rtp = nullptr; call->audio = nullptr; - rtp_kill(call->video_rtp); + rtp_kill(av->tox, call->video_rtp); vc_kill(call->video); call->video_rtp = nullptr; call->video = nullptr; @@ -1405,3 +1502,12 @@ static void call_kill_transmission(ToxAVCall *call) pthread_mutex_destroy(call->mutex_audio); pthread_mutex_destroy(call->mutex_video); } + +Mono_Time *toxav_get_av_mono_time(ToxAV *toxav) +{ + if (!toxav) { + return nullptr; + } + + return toxav->toxav_mono_time; +} diff --git a/toxav/toxav_hacks.h b/toxav/toxav_hacks.h new file mode 100644 index 0000000000..95a44b0afa --- /dev/null +++ b/toxav/toxav_hacks.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2016-2018 The TokTok team. + * Copyright © 2013-2015 Tox project. + */ +#ifndef C_TOXCORE_TOXAV_HACKS_H +#define C_TOXCORE_TOXAV_HACKS_H + +#include "bwcontroller.h" +#include "msi.h" +#include "rtp.h" + +#ifndef TOXAV_CALL_DEFINED +#define TOXAV_CALL_DEFINED +typedef struct ToxAVCall ToxAVCall; +#endif /* TOXAV_CALL_DEFINED */ + +ToxAVCall *call_get(ToxAV *av, uint32_t friend_number); +RTPSession *rtp_session_get(ToxAVCall *call, int payload_type); +MSISession *tox_av_msi_get(ToxAV *av); +BWController *bwc_controller_get(void *call); +Mono_Time *toxav_get_av_mono_time(ToxAV *toxav); + +#endif // C_TOXCORE_TOXAV_HACKS_H diff --git a/toxav/video.c b/toxav/video.c index 3d3714ebca..71016371c1 100644 --- a/toxav/video.c +++ b/toxav/video.c @@ -75,12 +75,12 @@ static vpx_codec_iface_t *video_codec_encoder_interface(void) #define VPX_MAX_DECODER_THREADS 4 #define VIDEO_VP8_DECODER_POST_PROCESSING_ENABLED 0 -static void vc_init_encoder_cfg(const Logger *log, vpx_codec_enc_cfg_t *cfg, int16_t kf_max_dist) +static void vc_init_encoder_cfg(Tox *tox, vpx_codec_enc_cfg_t *cfg, int16_t kf_max_dist) { vpx_codec_err_t rc = vpx_codec_enc_config_default(video_codec_encoder_interface(), cfg, 0); if (rc != VPX_CODEC_OK) { - LOGGER_ERROR(log, "vc_init_encoder_cfg:Failed to get config: %s", vpx_codec_err_to_string(rc)); + LOGGER_API_ERROR(tox, "vc_init_encoder_cfg:Failed to get config: %s", vpx_codec_err_to_string(rc)); } /* Target bandwidth to use for this stream, in kilobits per second */ @@ -115,10 +115,10 @@ static void vc_init_encoder_cfg(const Logger *log, vpx_codec_enc_cfg_t *cfg, int */ if (kf_max_dist > 1) { cfg->kf_max_dist = kf_max_dist; // a full frame every x frames minimum (can be more often, codec decides automatically) - LOGGER_DEBUG(log, "kf_max_dist=%d (1)", cfg->kf_max_dist); + LOGGER_API_DEBUG(tox, "kf_max_dist=%d (1)", cfg->kf_max_dist); } else { cfg->kf_max_dist = VPX_MAX_DIST_START; - LOGGER_DEBUG(log, "kf_max_dist=%d (2)", cfg->kf_max_dist); + LOGGER_API_DEBUG(tox, "kf_max_dist=%d (2)", cfg->kf_max_dist); } cfg->g_threads = VPX_MAX_ENCODER_THREADS; // Maximum number of threads to use @@ -144,19 +144,19 @@ static void vc_init_encoder_cfg(const Logger *log, vpx_codec_enc_cfg_t *cfg, int #endif } -VCSession *vc_new(Mono_Time *mono_time, const Logger *log, ToxAV *av, uint32_t friend_number, +VCSession *vc_new(Mono_Time *mono_time, Tox *tox, ToxAV *av, uint32_t friend_number, toxav_video_receive_frame_cb *cb, void *cb_data) { VCSession *vc = (VCSession *)calloc(sizeof(VCSession), 1); vpx_codec_err_t rc; if (!vc) { - LOGGER_WARNING(log, "Allocation failed! Application might misbehave!"); + LOGGER_API_WARNING(tox, "Allocation failed! Application might misbehave!"); return nullptr; } if (create_recursive_mutex(vc->queue_mutex) != 0) { - LOGGER_WARNING(log, "Failed to create recursive mutex!"); + LOGGER_API_WARNING(tox, "Failed to create recursive mutex!"); free(vc); return nullptr; } @@ -181,17 +181,17 @@ VCSession *vc_new(Mono_Time *mono_time, const Logger *log, ToxAV *av, uint32_t f dec_cfg.w = VIDEO_CODEC_DECODER_MAX_WIDTH; dec_cfg.h = VIDEO_CODEC_DECODER_MAX_HEIGHT; - LOGGER_DEBUG(log, "Using VP8 codec for decoder (0)"); + LOGGER_API_DEBUG(tox, "Using VP8 codec for decoder (0)"); rc = vpx_codec_dec_init(vc->decoder, video_codec_decoder_interface(), &dec_cfg, VPX_CODEC_USE_FRAME_THREADING | VPX_CODEC_USE_POSTPROC); if (rc == VPX_CODEC_INCAPABLE) { - LOGGER_WARNING(log, "Postproc not supported by this decoder (0)"); + LOGGER_API_WARNING(tox, "Postproc not supported by this decoder (0)"); rc = vpx_codec_dec_init(vc->decoder, video_codec_decoder_interface(), &dec_cfg, VPX_CODEC_USE_FRAME_THREADING); } if (rc != VPX_CODEC_OK) { - LOGGER_ERROR(log, "Init video_decoder failed: %s", vpx_codec_err_to_string(rc)); + LOGGER_API_ERROR(tox, "Init video_decoder failed: %s", vpx_codec_err_to_string(rc)); goto BASE_CLEANUP; } @@ -200,38 +200,38 @@ VCSession *vc_new(Mono_Time *mono_time, const Logger *log, ToxAV *av, uint32_t f vpx_codec_err_t cc_res = vpx_codec_control(vc->decoder, VP8_SET_POSTPROC, &pp); if (cc_res != VPX_CODEC_OK) { - LOGGER_WARNING(log, "Failed to turn on postproc"); + LOGGER_API_WARNING(tox, "Failed to turn on postproc"); } else { - LOGGER_DEBUG(log, "turn on postproc: OK"); + LOGGER_API_DEBUG(tox, "turn on postproc: OK"); } } else { vp8_postproc_cfg_t pp = {0, 0, 0}; vpx_codec_err_t cc_res = vpx_codec_control(vc->decoder, VP8_SET_POSTPROC, &pp); if (cc_res != VPX_CODEC_OK) { - LOGGER_WARNING(log, "Failed to turn OFF postproc"); + LOGGER_API_WARNING(tox, "Failed to turn OFF postproc"); } else { - LOGGER_DEBUG(log, "Disable postproc: OK"); + LOGGER_API_DEBUG(tox, "Disable postproc: OK"); } } /* Set encoder to some initial values */ vpx_codec_enc_cfg_t cfg; - vc_init_encoder_cfg(log, &cfg, 1); + vc_init_encoder_cfg(tox, &cfg, 1); - LOGGER_DEBUG(log, "Using VP8 codec for encoder (0.1)"); + LOGGER_API_DEBUG(tox, "Using VP8 codec for encoder (0.1)"); rc = vpx_codec_enc_init(vc->encoder, video_codec_encoder_interface(), &cfg, VPX_CODEC_USE_FRAME_THREADING); if (rc != VPX_CODEC_OK) { - LOGGER_ERROR(log, "Failed to initialize encoder: %s", vpx_codec_err_to_string(rc)); + LOGGER_API_ERROR(tox, "Failed to initialize encoder: %s", vpx_codec_err_to_string(rc)); goto BASE_CLEANUP_1; } rc = vpx_codec_control(vc->encoder, VP8E_SET_CPUUSED, cpu_used_value); if (rc != VPX_CODEC_OK) { - LOGGER_ERROR(log, "Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc)); + LOGGER_API_ERROR(tox, "Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc)); vpx_codec_destroy(vc->encoder); goto BASE_CLEANUP_1; } @@ -245,26 +245,29 @@ VCSession *vc_new(Mono_Time *mono_time, const Logger *log, ToxAV *av, uint32_t f rc = vpx_codec_control(vc->encoder, VP8E_SET_NOISE_SENSITIVITY, 2); if (rc != VPX_CODEC_OK) { - LOGGER_ERROR(log, "Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc)); + LOGGER_API_ERROR(tox, "Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc)); vpx_codec_destroy(vc->encoder); goto BASE_CLEANUP_1; } #endif + vc->linfts = current_time_monotonic(mono_time); vc->lcfd = 60; vc->vcb = cb; vc->vcb_user_data = cb_data; vc->friend_number = friend_number; vc->av = av; - vc->log = log; + vc->tox = tox; return vc; + BASE_CLEANUP_1: vpx_codec_destroy(vc->decoder); BASE_CLEANUP: pthread_mutex_destroy(vc->queue_mutex); rb_kill(vc->vbuf_raw); free(vc); + return nullptr; } @@ -284,7 +287,7 @@ void vc_kill(VCSession *vc) rb_kill(vc->vbuf_raw); pthread_mutex_destroy(vc->queue_mutex); - LOGGER_DEBUG(vc->log, "Terminated video handler: %p", (void *)vc); + LOGGER_API_DEBUG(vc->tox, "Terminated video handler: %p", (void *)vc); free(vc); } @@ -299,7 +302,7 @@ void vc_iterate(VCSession *vc) struct RTPMessage *p; if (!rb_read(vc->vbuf_raw, (void **)&p)) { - LOGGER_TRACE(vc->log, "no Video frame data available"); + LOGGER_API_TRACE(vc->tox, "no Video frame data available"); pthread_mutex_unlock(vc->queue_mutex); return; } @@ -312,19 +315,19 @@ void vc_iterate(VCSession *vc) if (header->flags & RTP_LARGE_FRAME) { full_data_len = header->data_length_full; - LOGGER_DEBUG(vc->log, "vc_iterate:001:full_data_len=%d", (int)full_data_len); + LOGGER_API_DEBUG(vc->tox, "vc_iterate:001:full_data_len=%d", (int)full_data_len); } else { full_data_len = p->len; - LOGGER_DEBUG(vc->log, "vc_iterate:002"); + LOGGER_API_DEBUG(vc->tox, "vc_iterate:002"); } - LOGGER_DEBUG(vc->log, "vc_iterate: rb_read p->len=%d p->header.xe=%d", (int)full_data_len, p->header.xe); - LOGGER_DEBUG(vc->log, "vc_iterate: rb_read rb size=%d", (int)log_rb_size); + LOGGER_API_DEBUG(vc->tox, "vc_iterate: rb_read p->len=%d p->header.xe=%d", (int)full_data_len, p->header.xe); + LOGGER_API_DEBUG(vc->tox, "vc_iterate: rb_read rb size=%d", (int)log_rb_size); const vpx_codec_err_t rc = vpx_codec_decode(vc->decoder, p->data, full_data_len, nullptr, MAX_DECODE_TIME_US); free(p); if (rc != VPX_CODEC_OK) { - LOGGER_ERROR(vc->log, "Error decoding video: %d %s", (int)rc, vpx_codec_err_to_string(rc)); + LOGGER_API_ERROR(vc->tox, "Error decoding video: %d %s", (int)rc, vpx_codec_err_to_string(rc)); return; } @@ -362,13 +365,13 @@ int vc_queue_message(Mono_Time *mono_time, void *vcp, struct RTPMessage *msg) const struct RTPHeader *const header = &msg->header; if (msg->header.pt == (RTP_TYPE_VIDEO + 2) % 128) { - LOGGER_WARNING(vc->log, "Got dummy!"); + LOGGER_API_WARNING(vc->tox, "Got dummy!"); free(msg); return 0; } if (msg->header.pt != RTP_TYPE_VIDEO % 128) { - LOGGER_WARNING(vc->log, "Invalid payload type! pt=%d", (int)msg->header.pt); + LOGGER_API_WARNING(vc->tox, "Invalid payload type! pt=%d", (int)msg->header.pt); free(msg); return -1; } @@ -376,7 +379,7 @@ int vc_queue_message(Mono_Time *mono_time, void *vcp, struct RTPMessage *msg) pthread_mutex_lock(vc->queue_mutex); if ((header->flags & RTP_LARGE_FRAME) && header->pt == RTP_TYPE_VIDEO % 128) { - LOGGER_DEBUG(vc->log, "rb_write msg->len=%d b0=%d b1=%d", (int)msg->len, (int)msg->data[0], (int)msg->data[1]); + LOGGER_API_DEBUG(vc->tox, "rb_write msg->len=%d b0=%d b1=%d", (int)msg->len, (int)msg->data[0], (int)msg->data[1]); } free(rb_write(vc->vbuf_raw, msg)); @@ -404,31 +407,31 @@ int vc_reconfigure_encoder(VCSession *vc, uint32_t bit_rate, uint16_t width, uin if (cfg2.g_w == width && cfg2.g_h == height && kf_max_dist == -1) { /* Only bit rate changed */ - LOGGER_INFO(vc->log, "bitrate change from: %u to: %u", (uint32_t)cfg2.rc_target_bitrate, (uint32_t)bit_rate); + LOGGER_API_INFO(vc->tox, "bitrate change from: %u to: %u", (uint32_t)cfg2.rc_target_bitrate, (uint32_t)bit_rate); cfg2.rc_target_bitrate = bit_rate; rc = vpx_codec_enc_config_set(vc->encoder, &cfg2); if (rc != VPX_CODEC_OK) { - LOGGER_ERROR(vc->log, "Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc)); + LOGGER_API_ERROR(vc->tox, "Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc)); return -1; } } else { /* Resolution is changed, must reinitialize encoder since libvpx v1.4 doesn't support * reconfiguring encoder to use resolutions greater than initially set. */ - LOGGER_DEBUG(vc->log, "Have to reinitialize vpx encoder on session %p", (void *)vc); + LOGGER_API_DEBUG(vc->tox, "Have to reinitialize vpx encoder on session %p", (void *)vc); vpx_codec_ctx_t new_c; vpx_codec_enc_cfg_t cfg; - vc_init_encoder_cfg(vc->log, &cfg, kf_max_dist); + vc_init_encoder_cfg(vc->tox, &cfg, kf_max_dist); cfg.rc_target_bitrate = bit_rate; cfg.g_w = width; cfg.g_h = height; - LOGGER_DEBUG(vc->log, "Using VP8 codec for encoder"); + LOGGER_API_DEBUG(vc->tox, "Using VP8 codec for encoder"); rc = vpx_codec_enc_init(&new_c, video_codec_encoder_interface(), &cfg, VPX_CODEC_USE_FRAME_THREADING); if (rc != VPX_CODEC_OK) { - LOGGER_ERROR(vc->log, "Failed to initialize encoder: %s", vpx_codec_err_to_string(rc)); + LOGGER_API_ERROR(vc->tox, "Failed to initialize encoder: %s", vpx_codec_err_to_string(rc)); return -1; } @@ -437,7 +440,7 @@ int vc_reconfigure_encoder(VCSession *vc, uint32_t bit_rate, uint16_t width, uin rc = vpx_codec_control(&new_c, VP8E_SET_CPUUSED, cpu_used_value); if (rc != VPX_CODEC_OK) { - LOGGER_ERROR(vc->log, "Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc)); + LOGGER_API_ERROR(vc->tox, "Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc)); vpx_codec_destroy(&new_c); return -1; } diff --git a/toxav/video.h b/toxav/video.h index 6be9ac7544..cee5f86847 100644 --- a/toxav/video.h +++ b/toxav/video.h @@ -22,6 +22,11 @@ #include +#ifndef TOX_DEFINED +#define TOX_DEFINED +typedef struct Tox Tox; +#endif /* TOX_DEFINED */ + typedef struct VCSession_s { /* encoding */ vpx_codec_ctx_t encoder[1]; @@ -34,7 +39,6 @@ typedef struct VCSession_s { uint64_t linfts; /* Last received frame time stamp */ uint32_t lcfd; /* Last calculated frame duration for incoming video payload */ - const Logger *log; ToxAV *av; uint32_t friend_number; @@ -43,9 +47,10 @@ typedef struct VCSession_s { void *vcb_user_data; pthread_mutex_t queue_mutex[1]; + Tox *tox; } VCSession; -VCSession *vc_new(Mono_Time *mono_time, const Logger *log, ToxAV *av, uint32_t friend_number, +VCSession *vc_new(Mono_Time *mono_time, Tox *tox, ToxAV *av, uint32_t friend_number, toxav_video_receive_frame_cb *cb, void *cb_data); void vc_kill(VCSession *vc); void vc_iterate(VCSession *vc); diff --git a/toxcore/BUILD.bazel b/toxcore/BUILD.bazel index 0fdfe0aec0..2b50352c24 100644 --- a/toxcore/BUILD.bazel +++ b/toxcore/BUILD.bazel @@ -4,7 +4,7 @@ load("//tools:no_undefined.bzl", "cc_library") filegroup( name = "public_headers", srcs = ["tox.h"], - visibility = ["//c-toxcore:__pkg__"], + visibility = ["//c-toxcore:__subpackages__"], ) cc_library( diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 556acc272f..15dc5a1a27 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -405,10 +405,6 @@ int m_delfriend(Messenger *m, int32_t friendnumber) return -1; } - if (m->friend_connectionstatuschange_internal) { - m->friend_connectionstatuschange_internal(m, friendnumber, 0, m->friend_connectionstatuschange_internal_userdata); - } - clear_receipts(m, friendnumber); remove_request_received(m->fr, m->friendlist[friendnumber].real_pk); friend_connection_callbacks(m->fr_c, m->friendlist[friendnumber].friendcon_id, MESSENGER_CALLBACK_INDEX, nullptr, @@ -881,13 +877,6 @@ void m_callback_core_connection(Messenger *m, m_self_connection_status_cb *funct m->core_connection_change = function; } -void m_callback_connectionstatus_internal_av(Messenger *m, m_friend_connectionstatuschange_internal_cb *function, - void *userdata) -{ - m->friend_connectionstatuschange_internal = function; - m->friend_connectionstatuschange_internal_userdata = userdata; -} - static void check_friend_tcp_udp(Messenger *m, int32_t friendnumber, void *userdata) { int last_connection_udp_tcp = m->friendlist[friendnumber].last_connection_udp_tcp; @@ -916,6 +905,7 @@ static void check_friend_tcp_udp(Messenger *m, int32_t friendnumber, void *userd } static void break_files(const Messenger *m, int32_t friendnumber); + static void check_friend_connectionstatus(Messenger *m, int32_t friendnumber, uint8_t status, void *userdata) { if (status == NOFRIEND) { @@ -939,11 +929,6 @@ static void check_friend_connectionstatus(Messenger *m, int32_t friendnumber, ui m->friendlist[friendnumber].status = status; check_friend_tcp_udp(m, friendnumber, userdata); - - if (m->friend_connectionstatuschange_internal) { - m->friend_connectionstatuschange_internal(m, friendnumber, is_online, - m->friend_connectionstatuschange_internal_userdata); - } } } @@ -1725,24 +1710,6 @@ static int handle_filecontrol(Messenger *m, int32_t friendnumber, uint8_t receiv } } -/* Set the callback for msi packets. - */ -void m_callback_msi_packet(Messenger *m, m_msi_packet_cb *function, void *userdata) -{ - m->msi_packet = function; - m->msi_packet_userdata = userdata; -} - -/* Send an msi packet. - * - * return 1 on success - * return 0 on failure - */ -int m_msi_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length) -{ - return write_cryptpacket_id(m, friendnumber, PACKET_ID_MSI, data, length, 0); -} - static int m_handle_lossy_packet(void *object, int friend_num, const uint8_t *packet, uint16_t length, void *userdata) { @@ -1752,17 +1719,6 @@ static int m_handle_lossy_packet(void *object, int friend_num, const uint8_t *pa return 1; } - if (packet[0] <= PACKET_ID_RANGE_LOSSY_AV_END) { - const RTP_Packet_Handler *const ph = - &m->friendlist[friend_num].lossy_rtp_packethandlers[packet[0] % PACKET_ID_RANGE_LOSSY_AV_SIZE]; - - if (ph->function) { - return ph->function(m, friend_num, packet, length, ph->object); - } - - return 1; - } - if (m->lossy_packethandler) { m->lossy_packethandler(m, friend_num, packet[0], packet, length, userdata); } @@ -1775,30 +1731,6 @@ void custom_lossy_packet_registerhandler(Messenger *m, m_friend_lossy_packet_cb m->lossy_packethandler = lossy_packethandler; } -int m_callback_rtp_packet(Messenger *m, int32_t friendnumber, uint8_t byte, m_lossy_rtp_packet_cb *function, - void *object) -{ - if (!friend_is_valid(m, friendnumber)) { - return -1; - } - - if (byte < PACKET_ID_RANGE_LOSSY_AV_START || byte > PACKET_ID_RANGE_LOSSY_AV_END) { - return -1; - } - - m->friendlist[friendnumber].lossy_rtp_packethandlers[byte % PACKET_ID_RANGE_LOSSY_AV_SIZE].function = function; - m->friendlist[friendnumber].lossy_rtp_packethandlers[byte % PACKET_ID_RANGE_LOSSY_AV_SIZE].object = object; - return 0; -} - - -/* TODO(oxij): this name is confusing, because this function sends both av and custom lossy packets. - * Meanwhile, m_handle_lossy_packet routes custom packets to custom_lossy_packet_registerhandler - * as you would expect from its name. - * - * I.e. custom_lossy_packet_registerhandler's "custom lossy packet" and this "custom lossy packet" - * are not the same set of packets. - */ int m_send_custom_lossy_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint32_t length) { if (!friend_is_valid(m, friendnumber)) { @@ -1809,7 +1741,6 @@ int m_send_custom_lossy_packet(const Messenger *m, int32_t friendnumber, const u return -2; } - // TODO(oxij): send_lossy_cryptpacket makes this check already, similarly for other similar places if (data[0] < PACKET_ID_RANGE_LOSSY_START || data[0] > PACKET_ID_RANGE_LOSSY_END) { return -3; } @@ -1836,7 +1767,10 @@ static int handle_custom_lossless_packet(void *object, int friend_num, const uin } if (packet[0] < PACKET_ID_RANGE_LOSSLESS_CUSTOM_START || packet[0] > PACKET_ID_RANGE_LOSSLESS_CUSTOM_END) { - return -1; + // allow PACKET_ID_MSI packets to be handled by custom packet handler + if (packet[0] != PACKET_ID_MSI) { + return -1; + } } if (m->lossless_packethandler) { @@ -2392,14 +2326,8 @@ static int m_handle_packet(void *object, int i, const uint8_t *temp, uint16_t le } case PACKET_ID_MSI: { - if (data_length == 0) { - break; - } - - if (m->msi_packet) { - (*m->msi_packet)(m, i, data, data_length, m->msi_packet_userdata); - } - + // allow MSI packets to be handled by custom packet handler + handle_custom_lossless_packet(object, i, temp, len, userdata); break; } diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 31526b631d..9425280cec 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -189,12 +189,8 @@ typedef void m_friend_lossy_packet_cb(Messenger *m, uint32_t friend_number, uint size_t length, void *user_data); typedef void m_friend_lossless_packet_cb(Messenger *m, uint32_t friend_number, uint8_t packet_id, const uint8_t *data, size_t length, void *user_data); -typedef void m_friend_connectionstatuschange_internal_cb(Messenger *m, uint32_t friend_number, - uint8_t connection_status, void *user_data); typedef void m_conference_invite_cb(Messenger *m, uint32_t friend_number, const uint8_t *cookie, uint16_t length, void *user_data); -typedef void m_msi_packet_cb(Messenger *m, uint32_t friend_number, const uint8_t *data, uint16_t length, - void *user_data); typedef int m_lossy_rtp_packet_cb(Messenger *m, uint32_t friendnumber, const uint8_t *data, uint16_t len, void *object); typedef struct RTP_Packet_Handler { @@ -230,8 +226,6 @@ typedef struct Friend { uint32_t num_sending_files; struct File_Transfers file_receiving[MAX_CONCURRENT_FILE_PIPES]; - RTP_Packet_Handler lossy_rtp_packethandlers[PACKET_ID_RANGE_LOSSY_AV_SIZE]; - struct Receipts *receipts_start; struct Receipts *receipts_end; } Friend; @@ -277,8 +271,6 @@ struct Messenger { m_friend_typing_cb *friend_typingchange; m_friend_read_receipt_cb *read_receipt; m_friend_connection_status_cb *friend_connectionstatuschange; - m_friend_connectionstatuschange_internal_cb *friend_connectionstatuschange_internal; - void *friend_connectionstatuschange_internal_userdata; struct Group_Chats *conferences_object; /* Set by new_groupchats()*/ m_conference_invite_cb *conference_invite; @@ -288,9 +280,6 @@ struct Messenger { m_file_recv_chunk_cb *file_filedata; m_file_chunk_request_cb *file_reqchunk; - m_msi_packet_cb *msi_packet; - void *msi_packet_userdata; - m_friend_lossy_packet_cb *lossy_packethandler; m_friend_lossless_packet_cb *lossless_packethandler; @@ -546,10 +535,6 @@ void m_callback_read_receipt(Messenger *m, m_friend_read_receipt_cb *function); */ void m_callback_connectionstatus(Messenger *m, m_friend_connection_status_cb *function); -/* Same as previous but for internal A/V core usage only */ -void m_callback_connectionstatus_internal_av(Messenger *m, m_friend_connectionstatuschange_internal_cb *function, - void *userdata); - /* Set the callback for typing changes. * Function(unsigned int connection_status (0 = not connected, 1 = TCP only, 2 = UDP + TCP)) @@ -651,26 +636,6 @@ int file_seek(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uin int file_data(const Messenger *m, int32_t friendnumber, uint32_t filenumber, uint64_t position, const uint8_t *data, uint16_t length); -/** A/V related */ - -/* Set the callback for msi packets. - */ -void m_callback_msi_packet(Messenger *m, m_msi_packet_cb *function, void *userdata); - -/* Send an msi packet. - * - * return 1 on success - * return 0 on failure - */ -int m_msi_packet(const Messenger *m, int32_t friendnumber, const uint8_t *data, uint16_t length); - -/* Set handlers for lossy rtp packets. - * - * return -1 on failure. - * return 0 on success. - */ -int m_callback_rtp_packet(Messenger *m, int32_t friendnumber, uint8_t byte, - m_lossy_rtp_packet_cb *function, void *object); /** CUSTOM PACKETS */ diff --git a/toxcore/logger.c b/toxcore/logger.c index 00e85c36ff..75b95ea05d 100644 --- a/toxcore/logger.c +++ b/toxcore/logger.c @@ -17,6 +17,7 @@ #include #include #include +#include struct Logger { @@ -119,3 +120,38 @@ void logger_write(const Logger *log, Logger_Level level, const char *file, int l log->callback(log->context, level, file, line, func, msg, log->userdata); } + +void logger_api_write(const Logger *log, Logger_Level level, const char *file, int line, const char *func, + const char *format, va_list args) +{ + if (!log) { +#ifdef USE_STDERR_LOGGER + log = &logger_stderr; +#else + fprintf(stderr, "NULL logger not permitted.\n"); + abort(); +#endif + } + + if (!log->callback) { + return; + } + + // Only pass the file name, not the entire file path, for privacy reasons. + // The full path may contain PII of the person compiling toxcore (their + // username and directory layout). + const char *filename = strrchr(file, '/'); + file = filename ? filename + 1 : file; +#if defined(_WIN32) || defined(__CYGWIN__) + // On Windows, the path separator *may* be a backslash, so we look for that + // one too. + const char *windows_filename = strrchr(file, '\\'); + file = windows_filename ? windows_filename + 1 : file; +#endif + + // Format message + char msg[1024]; + vsnprintf(msg, sizeof(msg), format, args); + + log->callback(log->context, level, file, line, func, msg, log->userdata); +} diff --git a/toxcore/logger.h b/toxcore/logger.h index cbd8752b9b..0833507612 100644 --- a/toxcore/logger.h +++ b/toxcore/logger.h @@ -10,6 +10,8 @@ #define C_TOXCORE_TOXCORE_LOGGER_H #include +#include +#include #include "ccompat.h" @@ -61,6 +63,40 @@ void logger_write( const Logger *log, Logger_Level level, const char *file, int line, const char *func, const char *format, ...) GNU_PRINTF(6, 7); +void logger_api_write(const Logger *log, Logger_Level level, const char *file, int line, const char *func, + const char *format, va_list args) GNU_PRINTF(6, 0); + + +/** + * ================================================================================================== + * toxcore public api call to logger, used by ToxAV + */ +#ifndef TOX_DEFINED +#define TOX_DEFINED +typedef struct Tox Tox; +#endif /* TOX_DEFINED */ + +void tox_logmsg(const Tox *tox, Logger_Level level, const char *file, int line, const char *func, const char *fmt, + ...) GNU_PRINTF(6, 7); + +#define LOGGER_API_TRACE(tox, ...) LOGGER_API_WRITE(tox, LOGGER_LEVEL_TRACE , __VA_ARGS__) +#define LOGGER_API_DEBUG(tox, ...) LOGGER_API_WRITE(tox, LOGGER_LEVEL_DEBUG , __VA_ARGS__) +#define LOGGER_API_INFO(tox, ...) LOGGER_API_WRITE(tox, LOGGER_LEVEL_INFO , __VA_ARGS__) +#define LOGGER_API_WARNING(tox, ...) LOGGER_API_WRITE(tox, LOGGER_LEVEL_WARNING, __VA_ARGS__) +#define LOGGER_API_ERROR(tox, ...) LOGGER_API_WRITE(tox, LOGGER_LEVEL_ERROR , __VA_ARGS__) + +#define LOGGER_API_WRITE(tox, level, ...) \ + do { \ + if (level >= MIN_LOGGER_LEVEL) { \ + tox_logmsg(tox, level, __FILE__, __LINE__, __func__, __VA_ARGS__); \ + } \ + } while (0) + +/** + * ================================================================================================== + */ + + #define LOGGER_WRITE(log, level, ...) \ do { \ diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 2851053bbf..14b639c035 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -115,9 +115,6 @@ typedef struct Crypto_Connection { uint8_t maximum_speed_reached; - /* Must be a pointer, because the struct is moved in memory */ - pthread_mutex_t *mutex; - dht_pk_cb *dht_pk_callback; void *dht_pk_callback_object; uint32_t dht_pk_callback_number; @@ -131,10 +128,6 @@ struct Net_Crypto { TCP_Connections *tcp_c; Crypto_Connection *crypto_connections; - pthread_mutex_t tcp_mutex; - - pthread_mutex_t connections_mutex; - unsigned int connection_use_counter; uint32_t crypto_connections_length; /* Length of connections array. */ @@ -673,7 +666,6 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t int direct_send_attempt = 0; - pthread_mutex_lock(conn->mutex); IP_Port ip_port = return_ip_port_connection(c, crypt_connection_id); // TODO(irungentoo): on bad networks, direct connections might not last indefinitely. @@ -685,11 +677,9 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t if (direct_connected) { if ((uint32_t)sendpacket(dht_get_net(c->dht), ip_port, data, length) == length) { - pthread_mutex_unlock(conn->mutex); return 0; } - pthread_mutex_unlock(conn->mutex); return -1; } @@ -705,19 +695,12 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, const uint8_t } } - pthread_mutex_unlock(conn->mutex); - pthread_mutex_lock(&c->tcp_mutex); int ret = send_packet_tcp_connection(c->tcp_c, conn->connection_number_tcp, data, length); - pthread_mutex_unlock(&c->tcp_mutex); - - pthread_mutex_lock(conn->mutex); if (ret == 0) { conn->last_tcp_sent = current_time_monotonic(c->mono_time); } - pthread_mutex_unlock(conn->mutex); - if (ret == 0 || direct_send_attempt) { return 0; } @@ -1068,19 +1051,16 @@ static int send_data_packet(Net_Crypto *c, int crypt_connection_id, const uint8_ return -1; } - pthread_mutex_lock(conn->mutex); VLA(uint8_t, packet, 1 + sizeof(uint16_t) + length + CRYPTO_MAC_SIZE); packet[0] = NET_PACKET_CRYPTO_DATA; memcpy(packet + 1, conn->sent_nonce + (CRYPTO_NONCE_SIZE - sizeof(uint16_t)), sizeof(uint16_t)); const int len = encrypt_data_symmetric(conn->shared_key, conn->sent_nonce, data, length, packet + 1 + sizeof(uint16_t)); if (len + 1 + sizeof(uint16_t) != SIZEOF_VLA(packet)) { - pthread_mutex_unlock(conn->mutex); return -1; } increment_nonce(conn->sent_nonce); - pthread_mutex_unlock(conn->mutex); return send_packet_to(c, crypt_connection_id, packet, SIZEOF_VLA(packet)); } @@ -1167,9 +1147,7 @@ static int64_t send_lossless_packet(Net_Crypto *c, int crypt_connection_id, cons dt.sent_time = 0; dt.length = length; memcpy(dt.data, data, length); - pthread_mutex_lock(conn->mutex); int64_t packet_num = add_data_end_of_buffer(c->log, &conn->send_array, &dt); - pthread_mutex_unlock(conn->mutex); if (packet_num == -1) { return -1; @@ -1471,18 +1449,7 @@ static void connection_kill(Net_Crypto *c, int crypt_connection_id, void *userda userdata); } - while (1) { /* TODO(irungentoo): is this really the best way to do this? */ - pthread_mutex_lock(&c->connections_mutex); - - if (!c->connection_use_counter) { - break; - } - - pthread_mutex_unlock(&c->connections_mutex); - } - crypto_kill(c, crypt_connection_id); - pthread_mutex_unlock(&c->connections_mutex); } /* Handle a received data packet. @@ -1584,9 +1551,7 @@ static int handle_data_packet_core(Net_Crypto *c, int crypt_connection_id, const } while (1) { - pthread_mutex_lock(conn->mutex); int ret = read_data_beg_buffer(c->log, &conn->recv_array, &dt); - pthread_mutex_unlock(conn->mutex); if (ret == -1) { break; @@ -1754,16 +1719,6 @@ static int realloc_cryptoconnection(Net_Crypto *c, uint32_t num) */ static int create_crypto_connection(Net_Crypto *c) { - while (1) { /* TODO(irungentoo): is this really the best way to do this? */ - pthread_mutex_lock(&c->connections_mutex); - - if (!c->connection_use_counter) { - break; - } - - pthread_mutex_unlock(&c->connections_mutex); - } - int id = -1; for (uint32_t i = 0; i < c->crypto_connections_length; ++i) { @@ -1788,23 +1743,9 @@ static int create_crypto_connection(Net_Crypto *c) c->crypto_connections[id].last_packets_left_rem = 0; c->crypto_connections[id].packet_send_rate_requested = 0; c->crypto_connections[id].last_packets_left_requested_rem = 0; - c->crypto_connections[id].mutex = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t)); - - if (c->crypto_connections[id].mutex == nullptr) { - pthread_mutex_unlock(&c->connections_mutex); - return -1; - } - - if (pthread_mutex_init(c->crypto_connections[id].mutex, nullptr) != 0) { - free(c->crypto_connections[id].mutex); - pthread_mutex_unlock(&c->connections_mutex); - return -1; - } - c->crypto_connections[id].status = CRYPTO_CONN_NO_CONNECTION; } - pthread_mutex_unlock(&c->connections_mutex); return id; } @@ -1831,8 +1772,6 @@ static int wipe_crypto_connection(Net_Crypto *c, int crypt_connection_id) uint32_t i; - pthread_mutex_destroy(c->crypto_connections[crypt_connection_id].mutex); - free(c->crypto_connections[crypt_connection_id].mutex); crypto_memzero(&c->crypto_connections[crypt_connection_id], sizeof(Crypto_Connection)); /* check if we can resize the connections array */ @@ -2010,9 +1949,7 @@ int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c) return -1; } - pthread_mutex_lock(&c->tcp_mutex); const int connection_number_tcp = new_tcp_connection_to(c->tcp_c, n_c->dht_public_key, crypt_connection_id); - pthread_mutex_unlock(&c->tcp_mutex); if (connection_number_tcp == -1) { wipe_crypto_connection(c, crypt_connection_id); @@ -2029,9 +1966,7 @@ int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c) conn->status = CRYPTO_CONN_NOT_CONFIRMED; if (create_send_handshake(c, crypt_connection_id, n_c->cookie, n_c->dht_public_key) != 0) { - pthread_mutex_lock(&c->tcp_mutex); kill_tcp_connection_to(c->tcp_c, conn->connection_number_tcp); - pthread_mutex_unlock(&c->tcp_mutex); wipe_crypto_connection(c, crypt_connection_id); return -1; } @@ -2067,9 +2002,7 @@ int new_crypto_connection(Net_Crypto *c, const uint8_t *real_public_key, const u Crypto_Connection *conn = &c->crypto_connections[crypt_connection_id]; - pthread_mutex_lock(&c->tcp_mutex); const int connection_number_tcp = new_tcp_connection_to(c->tcp_c, dht_public_key, crypt_connection_id); - pthread_mutex_unlock(&c->tcp_mutex); if (connection_number_tcp == -1) { wipe_crypto_connection(c, crypt_connection_id); @@ -2093,9 +2026,7 @@ int new_crypto_connection(Net_Crypto *c, const uint8_t *real_public_key, const u if (create_cookie_request(c, cookie_request, conn->dht_public_key, conn->cookie_request_number, conn->shared_key) != sizeof(cookie_request) || new_temp_packet(c, crypt_connection_id, cookie_request, sizeof(cookie_request)) != 0) { - pthread_mutex_lock(&c->tcp_mutex); kill_tcp_connection_to(c->tcp_c, conn->connection_number_tcp); - pthread_mutex_unlock(&c->tcp_mutex); wipe_crypto_connection(c, crypt_connection_id); return -1; } @@ -2153,11 +2084,7 @@ static int tcp_data_callback(void *object, int crypt_connection_id, const uint8_ return tcp_handle_cookie_request(c, conn->connection_number_tcp, data, length); } - // This unlocks the mutex that at this point is locked by do_tcp before - // calling do_tcp_connections. - pthread_mutex_unlock(&c->tcp_mutex); int ret = handle_packet_connection(c, crypt_connection_id, data, length, 0, userdata); - pthread_mutex_lock(&c->tcp_mutex); if (ret != 0) { return -1; @@ -2209,9 +2136,7 @@ int add_tcp_relay_peer(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port, return -1; } - pthread_mutex_lock(&c->tcp_mutex); int ret = add_tcp_relay_connection(c->tcp_c, conn->connection_number_tcp, ip_port, public_key); - pthread_mutex_unlock(&c->tcp_mutex); return ret; } @@ -2222,9 +2147,7 @@ int add_tcp_relay_peer(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port, */ int add_tcp_relay(Net_Crypto *c, IP_Port ip_port, const uint8_t *public_key) { - pthread_mutex_lock(&c->tcp_mutex); int ret = add_tcp_relay_global(c->tcp_c, ip_port, public_key); - pthread_mutex_unlock(&c->tcp_mutex); return ret; } @@ -2238,9 +2161,7 @@ int add_tcp_relay(Net_Crypto *c, IP_Port ip_port, const uint8_t *public_key) */ int get_random_tcp_con_number(Net_Crypto *c) { - pthread_mutex_lock(&c->tcp_mutex); int ret = get_random_tcp_onion_conn_number(c->tcp_c); - pthread_mutex_unlock(&c->tcp_mutex); return ret; } @@ -2252,9 +2173,7 @@ int get_random_tcp_con_number(Net_Crypto *c) */ int send_tcp_onion_request(Net_Crypto *c, unsigned int tcp_connections_number, const uint8_t *data, uint16_t length) { - pthread_mutex_lock(&c->tcp_mutex); int ret = tcp_send_onion_request(c->tcp_c, tcp_connections_number, data, length); - pthread_mutex_unlock(&c->tcp_mutex); return ret; } @@ -2271,18 +2190,14 @@ unsigned int copy_connected_tcp_relays(Net_Crypto *c, Node_format *tcp_relays, u return 0; } - pthread_mutex_lock(&c->tcp_mutex); unsigned int ret = tcp_copy_connected_relays(c->tcp_c, tcp_relays, num); - pthread_mutex_unlock(&c->tcp_mutex); return ret; } static void do_tcp(Net_Crypto *c, void *userdata) { - pthread_mutex_lock(&c->tcp_mutex); do_tcp_connections(c->tcp_c, userdata); - pthread_mutex_unlock(&c->tcp_mutex); uint32_t i; @@ -2304,13 +2219,9 @@ static void do_tcp(Net_Crypto *c, void *userdata) } if (direct_connected) { - pthread_mutex_lock(&c->tcp_mutex); set_tcp_connection_to_status(c->tcp_c, conn->connection_number_tcp, 0); - pthread_mutex_unlock(&c->tcp_mutex); } else { - pthread_mutex_lock(&c->tcp_mutex); set_tcp_connection_to_status(c->tcp_c, conn->connection_number_tcp, 1); - pthread_mutex_unlock(&c->tcp_mutex); } } } @@ -2464,15 +2375,12 @@ static int udp_handle_packet(void *object, IP_Port source, const uint8_t *packet return -1; } - pthread_mutex_lock(conn->mutex); - if (net_family_is_ipv4(source.ip.family)) { conn->direct_lastrecv_timev4 = mono_time_get(c->mono_time); } else { conn->direct_lastrecv_timev6 = mono_time_get(c->mono_time); } - pthread_mutex_unlock(conn->mutex); return 0; } @@ -2855,26 +2763,16 @@ int send_lossy_cryptpacket(Net_Crypto *c, int crypt_connection_id, const uint8_t return -1; } - pthread_mutex_lock(&c->connections_mutex); - ++c->connection_use_counter; - pthread_mutex_unlock(&c->connections_mutex); - Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); int ret = -1; if (conn) { - pthread_mutex_lock(conn->mutex); uint32_t buffer_start = conn->recv_array.buffer_start; uint32_t buffer_end = conn->send_array.buffer_end; - pthread_mutex_unlock(conn->mutex); ret = send_data_packet_helper(c, crypt_connection_id, buffer_start, buffer_end, data, length); } - pthread_mutex_lock(&c->connections_mutex); - --c->connection_use_counter; - pthread_mutex_unlock(&c->connections_mutex); - return ret; } @@ -2894,9 +2792,7 @@ int crypto_kill(Net_Crypto *c, int crypt_connection_id) send_kill_packet(c, crypt_connection_id); } - pthread_mutex_lock(&c->tcp_mutex); kill_tcp_connection_to(c->tcp_c, conn->connection_number_tcp); - pthread_mutex_unlock(&c->tcp_mutex); bs_list_remove(&c->ip_port_list, (uint8_t *)&conn->ip_portv4, crypt_connection_id); bs_list_remove(&c->ip_port_list, (uint8_t *)&conn->ip_portv6, crypt_connection_id); @@ -2992,13 +2888,6 @@ Net_Crypto *new_net_crypto(const Logger *log, Mono_Time *mono_time, DHT *dht, TC set_packet_tcp_connection_callback(temp->tcp_c, &tcp_data_callback, temp); set_oob_packet_tcp_connection_callback(temp->tcp_c, &tcp_oob_callback, temp); - if (create_recursive_mutex(&temp->tcp_mutex) != 0 || - pthread_mutex_init(&temp->connections_mutex, nullptr) != 0) { - kill_tcp_connections(temp->tcp_c); - free(temp); - return nullptr; - } - temp->dht = dht; new_keys(temp); @@ -3068,9 +2957,6 @@ void kill_net_crypto(Net_Crypto *c) crypto_kill(c, i); } - pthread_mutex_destroy(&c->tcp_mutex); - pthread_mutex_destroy(&c->connections_mutex); - kill_tcp_connections(c->tcp_c); bs_list_free(&c->ip_port_list); networking_registerhandler(dht_get_net(c->dht), NET_PACKET_COOKIE_REQUEST, nullptr, nullptr); diff --git a/toxcore/network.c b/toxcore/network.c index e5a5833109..085d6d6a32 100644 --- a/toxcore/network.c +++ b/toxcore/network.c @@ -553,7 +553,7 @@ int sendpacket(Networking_Core *net, IP_Port ip_port, const uint8_t *data, uint1 addr6->sin6_flowinfo = 0; addr6->sin6_scope_id = 0; } else { - LOGGER_WARNING(net->log, "unknown address type: %d", ip_port.ip.family.value); + LOGGER_DEBUG(net->log, "unknown address type: %d", ip_port.ip.family.value); return -1; } @@ -657,7 +657,7 @@ void networking_poll(Networking_Core *net, void *userdata) } if (!(net->packethandlers[data[0]].function)) { - LOGGER_WARNING(net->log, "[%02u] -- Packet has no handler", data[0]); + LOGGER_DEBUG(net->log, "[%02u] -- Packet has no handler", data[0]); continue; } diff --git a/toxcore/tox.api.h b/toxcore/tox.api.h index 3655617181..0e4a2bcc9e 100644 --- a/toxcore/tox.api.h +++ b/toxcore/tox.api.h @@ -2669,8 +2669,9 @@ namespace friend { */ FRIEND_NOT_CONNECTED, /** - * The first byte of data was not in the specified range for the packet type. - * This range is 192-254 for lossy, and 69, 160-191 for lossless packets. + * The first byte of data was not one of the permitted values; + * for lossy packets the first byte must be in the range 192-254, + * and for lossless packets it must be either 69 or in the range 160-191. */ INVALID, /** @@ -2716,7 +2717,7 @@ namespace friend { /** * Send a custom lossless packet to a friend. * - * The first byte of data must be in the range 69, 160-191. Maximum length of a + * The first byte of data must be either 69 or in the range 160-191. Maximum length of a * custom packet is $MAX_CUSTOM_PACKET_SIZE. * * Lossless packet behaviour is comparable to TCP (reliability, arrive in order) @@ -2737,6 +2738,9 @@ namespace friend { event lossy_packet const { /** + * tox_callback_friend_lossy_packet is the compatibility function to + * set callback for all packet IDs except those reserved for ToxAV + * * @param friend_number The friend number of the friend who sent a lossy packet. * @param data A byte array containing the received packet data. * @param length The length of the packet data byte array. diff --git a/toxcore/tox.c b/toxcore/tox.c index d2d3ed344f..41ef7d155c 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -21,6 +21,7 @@ #include #include +#include #include #include "Messenger.h" @@ -68,7 +69,7 @@ struct Tox { // XXX: Messenger *must* be the first member, because toxav casts its // `Tox *` to `Messenger **`. Messenger *m; - Mono_Time *mono_time; + Mono_Time *mono_time; /* mono_time also needs to be at THIS position, if you put something before it things will crash!! */ pthread_mutex_t *mutex; tox_self_connection_status_cb *self_connection_status_callback; @@ -120,7 +121,9 @@ static void tox_self_connection_status_handler(Messenger *m, unsigned int connec struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data; if (tox_data->tox->self_connection_status_callback != nullptr) { + unlock(tox_data->tox); tox_data->tox->self_connection_status_callback(tox_data->tox, (Tox_Connection)connection_status, tox_data->user_data); + lock(tox_data->tox); } } @@ -130,7 +133,9 @@ static void tox_friend_name_handler(Messenger *m, uint32_t friend_number, const struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data; if (tox_data->tox->friend_name_callback != nullptr) { + unlock(tox_data->tox); tox_data->tox->friend_name_callback(tox_data->tox, friend_number, name, length, tox_data->user_data); + lock(tox_data->tox); } } @@ -140,7 +145,9 @@ static void tox_friend_status_message_handler(Messenger *m, uint32_t friend_numb struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data; if (tox_data->tox->friend_status_message_callback != nullptr) { + unlock(tox_data->tox); tox_data->tox->friend_status_message_callback(tox_data->tox, friend_number, message, length, tox_data->user_data); + lock(tox_data->tox); } } @@ -149,7 +156,9 @@ static void tox_friend_status_handler(Messenger *m, uint32_t friend_number, unsi struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data; if (tox_data->tox->friend_status_callback != nullptr) { + unlock(tox_data->tox); tox_data->tox->friend_status_callback(tox_data->tox, friend_number, (Tox_User_Status)status, tox_data->user_data); + lock(tox_data->tox); } } @@ -159,8 +168,10 @@ static void tox_friend_connection_status_handler(Messenger *m, uint32_t friend_n struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data; if (tox_data->tox->friend_connection_status_callback != nullptr) { + unlock(tox_data->tox); tox_data->tox->friend_connection_status_callback(tox_data->tox, friend_number, (Tox_Connection)connection_status, tox_data->user_data); + lock(tox_data->tox); } } @@ -169,7 +180,9 @@ static void tox_friend_typing_handler(Messenger *m, uint32_t friend_number, bool struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data; if (tox_data->tox->friend_typing_callback != nullptr) { + unlock(tox_data->tox); tox_data->tox->friend_typing_callback(tox_data->tox, friend_number, is_typing, tox_data->user_data); + lock(tox_data->tox); } } @@ -178,7 +191,9 @@ static void tox_friend_read_receipt_handler(Messenger *m, uint32_t friend_number struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data; if (tox_data->tox->friend_read_receipt_callback != nullptr) { + unlock(tox_data->tox); tox_data->tox->friend_read_receipt_callback(tox_data->tox, friend_number, message_id, tox_data->user_data); + lock(tox_data->tox); } } @@ -188,7 +203,9 @@ static void tox_friend_request_handler(Messenger *m, const uint8_t *public_key, struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data; if (tox_data->tox->friend_request_callback != nullptr) { + unlock(tox_data->tox); tox_data->tox->friend_request_callback(tox_data->tox, public_key, message, length, tox_data->user_data); + lock(tox_data->tox); } } @@ -198,8 +215,10 @@ static void tox_friend_message_handler(Messenger *m, uint32_t friend_number, uns struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data; if (tox_data->tox->friend_message_callback != nullptr) { + unlock(tox_data->tox); tox_data->tox->friend_message_callback(tox_data->tox, friend_number, (Tox_Message_Type)type, message, length, tox_data->user_data); + lock(tox_data->tox); } } @@ -209,8 +228,10 @@ static void tox_file_recv_control_handler(Messenger *m, uint32_t friend_number, struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data; if (tox_data->tox->file_recv_control_callback != nullptr) { + unlock(tox_data->tox); tox_data->tox->file_recv_control_callback(tox_data->tox, friend_number, file_number, (Tox_File_Control)control, tox_data->user_data); + lock(tox_data->tox); } } @@ -220,8 +241,10 @@ static void tox_file_chunk_request_handler(Messenger *m, uint32_t friend_number, struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data; if (tox_data->tox->file_chunk_request_callback != nullptr) { + unlock(tox_data->tox); tox_data->tox->file_chunk_request_callback(tox_data->tox, friend_number, file_number, position, length, tox_data->user_data); + lock(tox_data->tox); } } @@ -231,8 +254,10 @@ static void tox_file_recv_handler(Messenger *m, uint32_t friend_number, uint32_t struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data; if (tox_data->tox->file_recv_callback != nullptr) { + unlock(tox_data->tox); tox_data->tox->file_recv_callback(tox_data->tox, friend_number, file_number, kind, file_size, filename, filename_length, tox_data->user_data); + lock(tox_data->tox); } } @@ -242,8 +267,10 @@ static void tox_file_recv_chunk_handler(Messenger *m, uint32_t friend_number, ui struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data; if (tox_data->tox->file_recv_chunk_callback != nullptr) { + unlock(tox_data->tox); tox_data->tox->file_recv_chunk_callback(tox_data->tox, friend_number, file_number, position, data, length, tox_data->user_data); + lock(tox_data->tox); } } @@ -253,8 +280,10 @@ static void tox_conference_invite_handler(Messenger *m, uint32_t friend_number, struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data; if (tox_data->tox->conference_invite_callback != nullptr) { + unlock(tox_data->tox); tox_data->tox->conference_invite_callback(tox_data->tox, friend_number, (Tox_Conference_Type)type, cookie, length, tox_data->user_data); + lock(tox_data->tox); } } @@ -263,7 +292,9 @@ static void tox_conference_connected_handler(Messenger *m, uint32_t conference_n struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data; if (tox_data->tox->conference_connected_callback != nullptr) { + unlock(tox_data->tox); tox_data->tox->conference_connected_callback(tox_data->tox, conference_number, tox_data->user_data); + lock(tox_data->tox); } } @@ -273,8 +304,10 @@ static void tox_conference_message_handler(Messenger *m, uint32_t conference_num struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data; if (tox_data->tox->conference_message_callback != nullptr) { + unlock(tox_data->tox); tox_data->tox->conference_message_callback(tox_data->tox, conference_number, peer_number, (Tox_Message_Type)type, message, length, tox_data->user_data); + lock(tox_data->tox); } } @@ -284,8 +317,10 @@ static void tox_conference_title_handler(Messenger *m, uint32_t conference_numbe struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data; if (tox_data->tox->conference_title_callback != nullptr) { + unlock(tox_data->tox); tox_data->tox->conference_title_callback(tox_data->tox, conference_number, peer_number, title, length, tox_data->user_data); + lock(tox_data->tox); } } @@ -295,8 +330,10 @@ static void tox_conference_peer_name_handler(Messenger *m, uint32_t conference_n struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data; if (tox_data->tox->conference_peer_name_callback != nullptr) { + unlock(tox_data->tox); tox_data->tox->conference_peer_name_callback(tox_data->tox, conference_number, peer_number, name, length, tox_data->user_data); + lock(tox_data->tox); } } @@ -305,7 +342,9 @@ static void tox_conference_peer_list_changed_handler(Messenger *m, uint32_t conf struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data; if (tox_data->tox->conference_peer_list_changed_callback != nullptr) { + unlock(tox_data->tox); tox_data->tox->conference_peer_list_changed_callback(tox_data->tox, conference_number, tox_data->user_data); + lock(tox_data->tox); } } @@ -318,8 +357,10 @@ static void tox_friend_lossy_packet_handler(Messenger *m, uint32_t friend_number struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data; if (tox_data->tox->friend_lossy_packet_callback_per_pktid[packet_id] != nullptr) { + unlock(tox_data->tox); tox_data->tox->friend_lossy_packet_callback_per_pktid[packet_id](tox_data->tox, friend_number, data, length, tox_data->user_data); + lock(tox_data->tox); } } @@ -332,8 +373,10 @@ static void tox_friend_lossless_packet_handler(Messenger *m, uint32_t friend_num struct Tox_Userdata *tox_data = (struct Tox_Userdata *)user_data; if (tox_data->tox->friend_lossless_packet_callback_per_pktid[packet_id] != nullptr) { + unlock(tox_data->tox); tox_data->tox->friend_lossless_packet_callback_per_pktid[packet_id](tox_data->tox, friend_number, data, length, tox_data->user_data); + lock(tox_data->tox); } } @@ -534,12 +577,7 @@ Tox *tox_new(const struct Tox_Options *options, Tox_Err_New *error) return nullptr; } - - pthread_mutexattr_t attr; - - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(tox->mutex, &attr); + pthread_mutex_init(tox->mutex, nullptr); } else { tox->mutex = nullptr; } @@ -620,7 +658,7 @@ void tox_kill(Tox *tox) } lock(tox); - LOGGER_ASSERT(tox->m->log, tox->m->msi_packet == nullptr, "Attempted to kill tox while toxav is still alive"); + // ToxAV // LOGGER_ASSERT(tox->m->log, tox->m->msi_packet == nullptr, "Attempted to kill tox while toxav is still alive"); kill_groupchats(tox->m->conferences_object); kill_messenger(tox->m); mono_time_free(tox->mono_time); @@ -2437,3 +2475,19 @@ uint16_t tox_self_get_tcp_port(const Tox *tox, Tox_Err_Get_Port *error) unlock(tox); return 0; } + +void tox_logmsg(const Tox *tox, Logger_Level level, const char *file, int line, const char *func, const char *fmt, ...) +{ + if (!tox) { + return; + } + + lock(tox); + va_list args; + va_start(args, fmt); + + logger_api_write(tox->m->log, level, file, line, func, fmt, args); + + va_end(args); + unlock(tox); +} diff --git a/toxcore/tox.h b/toxcore/tox.h index c9c0967a7f..b98c156ffe 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -3066,8 +3066,9 @@ typedef enum TOX_ERR_FRIEND_CUSTOM_PACKET { TOX_ERR_FRIEND_CUSTOM_PACKET_FRIEND_NOT_CONNECTED, /** - * The first byte of data was not in the specified range for the packet type. - * This range is 192-254 for lossy, and 69, 160-191 for lossless packets. + * The first byte of data was not one of the permitted values; + * for lossy packets the first byte must be in the range 192-254, + * and for lossless packets it must be either 69 or in the range 160-191. */ TOX_ERR_FRIEND_CUSTOM_PACKET_INVALID, @@ -3115,7 +3116,7 @@ bool tox_friend_send_lossy_packet(Tox *tox, uint32_t friend_number, const uint8_ /** * Send a custom lossless packet to a friend. * - * The first byte of data must be in the range 69, 160-191. Maximum length of a + * The first byte of data must be either 69 or in the range 160-191. Maximum length of a * custom packet is TOX_MAX_CUSTOM_PACKET_SIZE. * * Lossless packet behaviour is comparable to TCP (reliability, arrive in order) @@ -3132,6 +3133,9 @@ bool tox_friend_send_lossless_packet(Tox *tox, uint32_t friend_number, const uin TOX_ERR_FRIEND_CUSTOM_PACKET *error); /** + * tox_callback_friend_lossy_packet is the compatibility function to + * set callback for all packet IDs except those reserved for ToxAV + * * @param friend_number The friend number of the friend who sent a lossy packet. * @param data A byte array containing the received packet data. * @param length The length of the packet data byte array. diff --git a/toxcore/tox_api.c b/toxcore/tox_api.c index 63b4bea335..1a68b22f7c 100644 --- a/toxcore/tox_api.c +++ b/toxcore/tox_api.c @@ -84,7 +84,7 @@ void tox_options_default(struct Tox_Options *options) tox_options_set_proxy_type(options, TOX_PROXY_TYPE_NONE); tox_options_set_hole_punching_enabled(options, true); tox_options_set_local_discovery_enabled(options, true); - tox_options_set_experimental_thread_safety(options, false); + tox_options_set_experimental_thread_safety(options, true); } }