Commit eb3467af authored by Simon Morlat's avatar Simon Morlat
Browse files

on ios, start background task during network-critical operations of the channel.

parent 1b86808a
...@@ -30,9 +30,11 @@ AM_SILENT_RULES(yes) ...@@ -30,9 +30,11 @@ AM_SILENT_RULES(yes)
# Checks for programs. # Checks for programs.
dnl don't put anythingelse before AC_PROG_CC unless checking if macro still work for clang dnl don't put anythingelse before AC_PROG_CC unless checking if macro still work for clang
dnl because of tunnel library wrapper, C++ is required.
AC_PROG_CXX(["xcrun clang++" g++]) AC_PROG_CXX(["xcrun clang++" g++])
AC_PROG_CC(["xcrun clang" gcc]) AC_PROG_CC(["xcrun clang" gcc])
dnl because of tunnel library wrapper, C++ is required. AC_PROG_OBJC(["xcrun clang" gcc])
AM_PROG_CC_C_O AM_PROG_CC_C_O
dnl AC_PROG_CC_C99 dnl AC_PROG_CC_C99
...@@ -46,10 +48,13 @@ case "$target" in ...@@ -46,10 +48,13 @@ case "$target" in
CFLAGS="$CFLAGS -mmacosx-version-min=10.6" CFLAGS="$CFLAGS -mmacosx-version-min=10.6"
;; ;;
i386-apple*|armv6-apple*|armv7-apple*|armv7s-apple*) i386-apple*|armv6-apple*|armv7-apple*|armv7s-apple*)
LIBS="$LIBS -framework CoreFoundation -framework CFNetwork " LIBS="$LIBS -framework Foundation -framework CoreFoundation -framework CFNetwork -framework UIKit"
;; build_ios=yes
;;
esac esac
AM_CONDITIONAL([BUILD_IOS], [test "x$build_ios" = "xyes"])
dnl Workaround for mingw, whose compiler doesn't check in /usr/include ... dnl Workaround for mingw, whose compiler doesn't check in /usr/include ...
case "$target_os" in case "$target_os" in
*mingw*) *mingw*)
...@@ -60,9 +65,9 @@ case "$target_os" in ...@@ -60,9 +65,9 @@ case "$target_os" in
fi fi
fi fi
;; ;;
esac esac
if test -f /etc/debian_version ; then if test -f /etc/debian_version ; then
use_deb=true; use_deb=true;
else else
......
...@@ -52,6 +52,10 @@ libbellesip_la_SOURCES= \ ...@@ -52,6 +52,10 @@ libbellesip_la_SOURCES= \
http-listener.c http-listener.c
if BUILD_IOS
libbellesip_la_SOURCES+=backgroundtask.m
endif
if BUILD_TUNNEL if BUILD_TUNNEL
libbellesip_la_SOURCES+= transports/tunnel_listeningpoint.c \ libbellesip_la_SOURCES+= transports/tunnel_listeningpoint.c \
transports/tunnel_channel.c \ transports/tunnel_channel.c \
......
/*
belle-sip - SIP (RFC3261) library.
Copyright (C) 2010 Belledonne Communications SARL
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "belle_sip_internal.h"
#include <UIKit/UIApplication.h>
unsigned int belle_sip_begin_background_task(const char *name, belle_sip_background_task_end_callback_t cb, void *data){
UIApplication *app=[UIApplication sharedApplication];
UIBackgroundTaskIdentifier bgid=[app beginBackgroundTaskWithExpirationHandler:^{
cb(data);
}];
if (bgid==UIBackgroundTaskInvalid){
belle_sip_error("Could not start background task.");
return 0;
}
return (unsigned int)bgid;
}
void belle_sip_end_background_task(unsigned int id){
UIApplication *app=[UIApplication sharedApplication];
[app endBackgroundTask:(UIBackgroundTaskIdentifier)id];
}
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
static void channel_prepare_continue(belle_sip_channel_t *obj); static void channel_prepare_continue(belle_sip_channel_t *obj);
static void channel_process_queue(belle_sip_channel_t *obj); static void channel_process_queue(belle_sip_channel_t *obj);
static void channel_begin_background_task(belle_sip_channel_t *obj);
static void channel_end_background_task(belle_sip_channel_t *obj);
const char *belle_sip_channel_state_to_string(belle_sip_channel_state_t state){ const char *belle_sip_channel_state_to_string(belle_sip_channel_state_t state){
switch(state){ switch(state){
...@@ -67,6 +69,8 @@ static void belle_sip_channel_destroy(belle_sip_channel_t *obj){ ...@@ -67,6 +69,8 @@ static void belle_sip_channel_destroy(belle_sip_channel_t *obj){
belle_sip_object_unref(obj->inactivity_timer); belle_sip_object_unref(obj->inactivity_timer);
} }
if (obj->public_ip) belle_sip_free(obj->public_ip); if (obj->public_ip) belle_sip_free(obj->public_ip);
channel_end_background_task(obj);/*normally this should do nothing because it sould have been terminated already,
however leaving a background task open is so dangerous that we have to be paranoid*/
belle_sip_message("Channel [%p] destroyed",obj); belle_sip_message("Channel [%p] destroyed",obj);
} }
...@@ -659,6 +663,27 @@ const struct addrinfo * belle_sip_channel_get_peer(belle_sip_channel_t *obj){ ...@@ -659,6 +663,27 @@ const struct addrinfo * belle_sip_channel_get_peer(belle_sip_channel_t *obj){
return obj->current_peer; return obj->current_peer;
} }
static void channel_on_background_task_ended(belle_sip_channel_t *obj){
belle_sip_warning("channel [%p]: background task has to be ended now, but work isn't finished.",obj);
channel_end_background_task(obj);
}
static void channel_begin_background_task(belle_sip_channel_t *obj){
if (obj->bg_task_id==0){
obj->bg_task_id=belle_sip_begin_background_task("belle-sip channel in progress",(void (*)(void*))channel_on_background_task_ended, obj);
if (obj->bg_task_id) belle_sip_message("channel [%p]: starting background task with id=[%x].",obj,obj->bg_task_id);
}else belle_sip_warning("channel [%p]: already a background task pending.",obj);
}
static void channel_end_background_task(belle_sip_channel_t *obj){
if (obj->bg_task_id){
belle_sip_message("channel [%p]: ending background task with id=[%x].",obj,obj->bg_task_id);
belle_sip_end_background_task(obj->bg_task_id);
obj->bg_task_id=0;
}
}
belle_sip_message_t* belle_sip_channel_pick_message(belle_sip_channel_t *obj) { belle_sip_message_t* belle_sip_channel_pick_message(belle_sip_channel_t *obj) {
belle_sip_message_t* result=NULL; belle_sip_message_t* result=NULL;
belle_sip_list_t* front; belle_sip_list_t* front;
...@@ -701,6 +726,7 @@ static void belle_sip_channel_handle_error(belle_sip_channel_t *obj){ ...@@ -701,6 +726,7 @@ static void belle_sip_channel_handle_error(belle_sip_channel_t *obj){
}/*else the channel was previously working good with the current ip address but now fails, so let's notify the error*/ }/*else the channel was previously working good with the current ip address but now fails, so let's notify the error*/
obj->state=BELLE_SIP_CHANNEL_ERROR; obj->state=BELLE_SIP_CHANNEL_ERROR;
channel_end_background_task(obj);
/*Because error notification will in practice trigger the destruction of possible transactions and this channel, /*Because error notification will in practice trigger the destruction of possible transactions and this channel,
* it is safer to invoke the listener outside the current call stack. * it is safer to invoke the listener outside the current call stack.
* Indeed the channel encounters network errors while being called for transmiting by a transaction. * Indeed the channel encounters network errors while being called for transmiting by a transaction.
...@@ -725,6 +751,9 @@ void channel_set_state(belle_sip_channel_t *obj, belle_sip_channel_state_t state ...@@ -725,6 +751,9 @@ void channel_set_state(belle_sip_channel_t *obj, belle_sip_channel_state_t state
belle_sip_channel_handle_error(obj); belle_sip_channel_handle_error(obj);
}else{ }else{
obj->state=state; obj->state=state;
if (state==BELLE_SIP_CHANNEL_DISCONNECTED){
channel_end_background_task(obj);
}
channel_invoke_state_listener(obj); channel_invoke_state_listener(obj);
} }
} }
...@@ -823,6 +852,7 @@ static belle_sip_message_t *channel_pop_outgoing(belle_sip_channel_t *obj){ ...@@ -823,6 +852,7 @@ static belle_sip_message_t *channel_pop_outgoing(belle_sip_channel_t *obj){
static void channel_prepare_continue(belle_sip_channel_t *obj){ static void channel_prepare_continue(belle_sip_channel_t *obj){
switch(obj->state){ switch(obj->state){
case BELLE_SIP_CHANNEL_INIT: case BELLE_SIP_CHANNEL_INIT:
channel_begin_background_task(obj);
belle_sip_channel_resolve(obj); belle_sip_channel_resolve(obj);
break; break;
case BELLE_SIP_CHANNEL_RES_DONE: case BELLE_SIP_CHANNEL_RES_DONE:
...@@ -870,6 +900,7 @@ void belle_sip_channel_set_ready(belle_sip_channel_t *obj, const struct sockaddr ...@@ -870,6 +900,7 @@ void belle_sip_channel_set_ready(belle_sip_channel_t *obj, const struct sockaddr
} }
channel_set_state(obj,BELLE_SIP_CHANNEL_READY); channel_set_state(obj,BELLE_SIP_CHANNEL_READY);
channel_process_queue(obj); channel_process_queue(obj);
channel_end_background_task(obj);
} }
static void channel_res_done(void *data, const char *name, struct addrinfo *ai_list){ static void channel_res_done(void *data, const char *name, struct addrinfo *ai_list){
...@@ -961,5 +992,16 @@ belle_sip_channel_t *belle_sip_channel_find_from_list(belle_sip_list_t *l, int a ...@@ -961,5 +992,16 @@ belle_sip_channel_t *belle_sip_channel_find_from_list(belle_sip_list_t *l, int a
return chan; return chan;
} }
#if !TARGET_OS_IPHONE
/*defines stubs*/
unsigned int belle_sip_begin_background_task(const char *name, belle_sip_background_task_end_callback_t cb, void *data){
return 0;
}
void belle_sip_end_background_task(unsigned int id){
return;
}
#endif
...@@ -25,6 +25,11 @@ ...@@ -25,6 +25,11 @@
#endif #endif
typedef void (*belle_sip_background_task_end_callback_t)(void *);
unsigned int belle_sip_begin_background_task(const char *name, belle_sip_background_task_end_callback_t cb, void *data);
void belle_sip_end_background_task(unsigned int id);
#define belle_sip_network_buffer_size 65535 #define belle_sip_network_buffer_size 65535
typedef enum belle_sip_channel_state{ typedef enum belle_sip_channel_state{
...@@ -101,6 +106,7 @@ struct belle_sip_channel{ ...@@ -101,6 +106,7 @@ struct belle_sip_channel{
belle_sip_source_t *inactivity_timer; belle_sip_source_t *inactivity_timer;
uint64_t last_recv_time; uint64_t last_recv_time;
int simulated_recv_return; /* used to simulate network error. 0= no data (disconnected) >0= do nothing -1= network error*/ int simulated_recv_return; /* used to simulate network error. 0= no data (disconnected) >0= do nothing -1= network error*/
unsigned bg_task_id;
unsigned char force_close; /* when channel is intentionnaly disconnected, in order to prevent looping notifications*/ unsigned char force_close; /* when channel is intentionnaly disconnected, in order to prevent looping notifications*/
unsigned char learnt_ip_port; unsigned char learnt_ip_port;
unsigned char has_name; /*set when the name of the peer is known, which is not the case of inboud connections*/ unsigned char has_name; /*set when the name of the peer is known, which is not the case of inboud connections*/
......
...@@ -71,7 +71,7 @@ int stream_channel_recv(belle_sip_stream_channel_t *obj, void *buf, size_t bufle ...@@ -71,7 +71,7 @@ int stream_channel_recv(belle_sip_stream_channel_t *obj, void *buf, size_t bufle
void stream_channel_close(belle_sip_stream_channel_t *obj){ void stream_channel_close(belle_sip_stream_channel_t *obj){
belle_sip_socket_t sock = belle_sip_source_get_socket((belle_sip_source_t*)obj); belle_sip_socket_t sock = belle_sip_source_get_socket((belle_sip_source_t*)obj);
if (sock!=(belle_sip_socket_t)-1){ if (sock!=(belle_sip_socket_t)-1){
#ifdef TARGET_OS_IPHONE #if TARGET_OS_IPHONE
if (obj->read_stream != NULL) { if (obj->read_stream != NULL) {
CFReadStreamClose (obj->read_stream); CFReadStreamClose (obj->read_stream);
CFRelease (obj->read_stream); CFRelease (obj->read_stream);
...@@ -87,7 +87,7 @@ void stream_channel_close(belle_sip_stream_channel_t *obj){ ...@@ -87,7 +87,7 @@ void stream_channel_close(belle_sip_stream_channel_t *obj){
} }
} }
#ifdef TARGET_OS_IPHONE #if TARGET_OS_IPHONE
static void stream_channel_enable_ios_background_mode(belle_sip_stream_channel_t *obj){ static void stream_channel_enable_ios_background_mode(belle_sip_stream_channel_t *obj){
int sock=belle_sip_source_get_socket((belle_sip_source_t*)obj); int sock=belle_sip_source_get_socket((belle_sip_source_t*)obj);
......
...@@ -19,6 +19,7 @@ belle_sip_tester_SOURCES= belle_sip_tester.c belle_sip_tester.h\ ...@@ -19,6 +19,7 @@ belle_sip_tester_SOURCES= belle_sip_tester.c belle_sip_tester.h\
register_tester.h \ register_tester.h \
belle_http_tester.c belle_http_tester.c
belle_sip_tester_CFLAGS=$(CUNIT_CFLAGS) $(STRICT_OPTIONS) $(TLS_CFLAGS) belle_sip_tester_CFLAGS=$(CUNIT_CFLAGS) $(STRICT_OPTIONS) $(TLS_CFLAGS)
belle_sip_tester_LDFLAGS=$(CUNIT_LIBS) $(AM_LDFLAGS) belle_sip_tester_LDFLAGS=$(CUNIT_LIBS) $(AM_LDFLAGS)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment