Compare commits

...

8 Commits

Author SHA1 Message Date
sauwming bb2287b3a8 Changed version to 2.13.1 2023-07-05 11:59:07 +08:00
Riza Sulistyo 806b7c2f7e Don't call SSL_shutdown() when receiving SSL_ERROR_SYSCALL or SSL_ERROR_SSL (#3577) 2023-07-05 11:53:13 +08:00
Matthew Fredrickson bbf7f229de Locking fix so that SSL_shutdown and SSL_write are not called at same time (#3583) 2023-07-05 11:52:54 +08:00
sauwming 6d72311fc8 Merge pull request from GHSA-q9cp-8wcq-7pfr
* Prevent heap buffer overflow when parsing DNS packet

* Fixed incorrect check in get_name*()
2023-07-05 11:51:41 +08:00
sauwming 4cea72a4db Merge pull request from GHSA-cxwq-5g9x-x7fr
* Fixed heap buffer overflow when parsing STUN errcode attribute

* Also fixed uint parsing
2023-07-05 11:51:22 +08:00
Nanang Izzuddin 563f34c097 Merge pull request from GHSA-9pfh-r8x4-w26w
* Fix buffer overread in STUN message decoder

* Updates based on comments
2023-07-05 11:50:47 +08:00
Nanang Izzuddin 24006a72c9 Fix bug in video conference in disconnecting ports (#3325) 2023-07-05 11:49:54 +08:00
sauwming f1e6313389 Fixed native iOS preview issue (#3350) 2023-07-05 11:48:58 +08:00
12 changed files with 195 additions and 97 deletions

View File

@ -127,6 +127,9 @@ static pj_status_t get_name_len(int rec_counter, const pj_uint8_t *pkt,
return PJLIB_UTIL_EDNSINNAMEPTR;
}
if (start >= max)
return PJLIB_UTIL_EDNSINNAMEPTR;
*name_len = *parsed_len = 0;
p = start;
while (*p) {
@ -199,6 +202,9 @@ static pj_status_t get_name(int rec_counter, const pj_uint8_t *pkt,
return PJLIB_UTIL_EDNSINNAMEPTR;
}
if (start >= max)
return PJLIB_UTIL_EDNSINNAMEPTR;
p = start;
while (*p) {
if ((*p & 0xc0) == 0xc0) {
@ -359,10 +365,14 @@ static pj_status_t parse_rr(pj_dns_parsed_rr *rr, pj_pool_t *pool,
/* Parse some well known records */
if (rr->type == PJ_DNS_TYPE_A) {
if (p + 4 > max)
return PJLIB_UTIL_EDNSINSIZE;
pj_memcpy(&rr->rdata.a.ip_addr, p, 4);
p += 4;
} else if (rr->type == PJ_DNS_TYPE_AAAA) {
if (p + 16 > max)
return PJLIB_UTIL_EDNSINSIZE;
pj_memcpy(&rr->rdata.aaaa.ip_addr, p, 16);
p += 16;
@ -388,6 +398,8 @@ static pj_status_t parse_rr(pj_dns_parsed_rr *rr, pj_pool_t *pool,
p += name_part_len;
} else if (rr->type == PJ_DNS_TYPE_SRV) {
if (p + 6 > max)
return PJLIB_UTIL_EDNSINSIZE;
/* Priority */
pj_memcpy(&rr->rdata.srv.prio, p, 2);

View File

@ -1409,7 +1409,7 @@ PJ_BEGIN_DECL
#define PJ_VERSION_NUM_MINOR 13
/** PJLIB version revision number. */
#define PJ_VERSION_NUM_REV 0
#define PJ_VERSION_NUM_REV 1
/**
* Extra suffix for the version (e.g. "-trunk"), or empty for

View File

@ -244,6 +244,7 @@ static void ssl_close_sockets(pj_ssl_sock_t *ssock)
static pj_bool_t on_handshake_complete(pj_ssl_sock_t *ssock,
pj_status_t status)
{
ssock->handshake_status = status;
/* Cancel handshake timer */
if (ssock->timer.id == TIMER_HANDSHAKE_TIMEOUT) {
pj_timer_heap_cancel(ssock->param.timer_heap, &ssock->timer);

View File

@ -112,6 +112,7 @@ struct pj_ssl_sock_t
pj_ioqueue_op_key_t shutdown_op_key;
pj_timer_entry timer;
pj_status_t verify_status;
pj_status_t handshake_status;
pj_bool_t is_closing;
unsigned long last_err;

View File

@ -1695,8 +1695,16 @@ static void ssl_destroy(pj_ssl_sock_t *ssock)
/* Reset SSL socket state */
static void ssl_reset_sock_state(pj_ssl_sock_t *ssock)
{
int post_unlock_flush_circ_buf = 0;
ossl_sock_t *ossock = (ossl_sock_t *)ssock;
/* Must lock around SSL calls, particularly SSL_shutdown
* as it can modify the write BIOs and destructively
* interfere with any ssl_write() calls in progress
* above in a multithreaded environment */
pj_lock_acquire(ssock->write_mutex);
/* Detach from SSL instance */
if (ossock->ossl_ssl) {
SSL_set_ex_data(ossock->ossl_ssl, sslsock_idx, NULL);
@ -1706,19 +1714,32 @@ static void ssl_reset_sock_state(pj_ssl_sock_t *ssock)
* Avoid calling SSL_shutdown() if handshake wasn't completed.
* OpenSSL 1.0.2f complains if SSL_shutdown() is called during an
* SSL handshake, while previous versions always return 0.
* Call SSL_shutdown() when there is a timeout handshake failure or
* the last error is not SSL_ERROR_SYSCALL and not SSL_ERROR_SSL.
*/
if (ossock->ossl_ssl && SSL_in_init(ossock->ossl_ssl) == 0) {
int ret = SSL_shutdown(ossock->ossl_ssl);
if (ret == 0) {
/* Flush data to send close notify. */
flush_circ_buf_output(ssock, &ssock->shutdown_op_key, 0, 0);
if (ssock->handshake_status == PJ_ETIMEDOUT ||
(ssock->last_err != SSL_ERROR_SYSCALL &&
ssock->last_err != SSL_ERROR_SSL))
{
int ret = SSL_shutdown(ossock->ossl_ssl);
if (ret == 0) {
/* SSL_shutdown will potentially trigger a bunch of
* data to dump to the socket */
post_unlock_flush_circ_buf = 1;
}
}
}
pj_lock_acquire(ssock->write_mutex);
ssock->ssl_state = SSL_STATE_NULL;
pj_lock_release(ssock->write_mutex);
if (post_unlock_flush_circ_buf) {
/* Flush data to send close notify. */
flush_circ_buf_output(ssock, &ssock->shutdown_op_key, 0, 0);
}
ssl_close_sockets(ssock);
/* Upon error, OpenSSL may leave any error description in the thread
@ -2413,7 +2434,6 @@ static pj_status_t ssl_read(pj_ssl_sock_t *ssock, void *data, int *size)
*/
pj_lock_acquire(ssock->write_mutex);
*size = size_ = SSL_read(ossock->ossl_ssl, data, size_);
pj_lock_release(ssock->write_mutex);
if (size_ <= 0) {
pj_status_t status;
@ -2436,15 +2456,22 @@ static pj_status_t ssl_read(pj_ssl_sock_t *ssock, void *data, int *size)
/* Reset SSL socket state, then return PJ_FALSE */
status = STATUS_FROM_SSL_ERR2("Read", ssock, size_,
err, len);
pj_lock_release(ssock->write_mutex);
/* Unfortunately we can't hold the lock here to reset all the state.
* We probably should though.
*/
ssl_reset_sock_state(ssock);
return status;
}
}
pj_lock_release(ssock->write_mutex);
/* Need renegotiation */
return PJ_EEOF;
}
pj_lock_release(ssock->write_mutex);
return PJ_SUCCESS;
}

View File

@ -36,13 +36,8 @@
#define THIS_FILE "darwin_dev.m"
#define DEFAULT_CLOCK_RATE 90000
#if TARGET_OS_IPHONE
#define DEFAULT_WIDTH 352
#define DEFAULT_HEIGHT 288
#else
#define DEFAULT_WIDTH 1280
#define DEFAULT_HEIGHT 720
#endif
#define DEFAULT_WIDTH 640
#define DEFAULT_HEIGHT 480
#define DEFAULT_FPS 15
/* Define whether we should maintain the aspect ratio when rotating the image.
@ -144,7 +139,6 @@ struct darwin_stream
AVCaptureVideoDataOutput *video_output;
VOutDelegate *vout_delegate;
dispatch_queue_t queue;
AVCaptureVideoPreviewLayer *prev_layer;
pj_bool_t is_running;
#if TARGET_OS_IPHONE
@ -153,6 +147,8 @@ struct darwin_stream
pj_size_t render_buf_size;
CGDataProviderRef render_data_provider;
UIView *render_view;
AVCaptureVideoPreviewLayer *prev_layer;
UIView *prev_view;
#endif
pj_timestamp frame_ts;
@ -236,6 +232,7 @@ static void set_preset_str()
#endif
}
#if TARGET_OS_IPHONE
static void dispatch_sync_on_main_queue(void (^block)(void))
{
if ([NSThread isMainThread]) {
@ -244,6 +241,7 @@ static void dispatch_sync_on_main_queue(void (^block)(void))
dispatch_sync(dispatch_get_main_queue(), block);
}
}
#endif
/****************************************************************************
* Factory operations
@ -1018,11 +1016,18 @@ static pj_status_t darwin_stream_get_cap(pjmedia_vid_dev_stream *s,
switch (cap) {
#if TARGET_OS_IPHONE
case PJMEDIA_VID_DEV_CAP_INPUT_PREVIEW:
{
pjmedia_vid_dev_hwnd *hwnd = (pjmedia_vid_dev_hwnd *) pval;
hwnd->type = PJMEDIA_VID_DEV_HWND_TYPE_IOS;
hwnd->info.ios.window = (void *)strm->prev_view;
return PJ_SUCCESS;
}
case PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW:
{
pjmedia_vid_dev_hwnd *hwnd = (pjmedia_vid_dev_hwnd*) pval;
hwnd->type = PJMEDIA_VID_DEV_HWND_TYPE_NONE;
hwnd->info.ios.window = (void*)strm->render_view;
pjmedia_vid_dev_hwnd *hwnd = (pjmedia_vid_dev_hwnd *) pval;
hwnd->type = PJMEDIA_VID_DEV_HWND_TYPE_IOS;
hwnd->info.ios.window = (void *)strm->render_view;
return PJ_SUCCESS;
}
#endif /* TARGET_OS_IPHONE */
@ -1043,6 +1048,7 @@ static pj_status_t darwin_stream_set_cap(pjmedia_vid_dev_stream *s,
PJ_ASSERT_RETURN(s && pval, PJ_EINVAL);
switch (cap) {
#if TARGET_OS_IPHONE
/* Native preview */
case PJMEDIA_VID_DEV_CAP_INPUT_PREVIEW:
{
@ -1053,7 +1059,8 @@ static pj_status_t darwin_stream_set_cap(pjmedia_vid_dev_stream *s,
if (strm->prev_layer) {
CALayer *prev_layer = strm->prev_layer;
dispatch_sync_on_main_queue(^{
[prev_layer removeFromSuperlayer];
if ([prev_layer superlayer])
[prev_layer removeFromSuperlayer];
[prev_layer release];
});
strm->prev_layer = nil;
@ -1072,29 +1079,34 @@ static pj_status_t darwin_stream_set_cap(pjmedia_vid_dev_stream *s,
if (!strm->cap_session)
return PJ_EINVALIDOP;
#if TARGET_OS_IPHONE
/* Preview layer instantiation should be in main thread! */
dispatch_sync_on_main_queue(^{
/* Create view, if none */
if (!strm->render_view)
darwin_init_view(strm);
/* Create preview layer */
AVCaptureVideoPreviewLayer *prev_layer =
[[AVCaptureVideoPreviewLayer alloc]
initWithSession:strm->cap_session];
/* Attach preview layer to a UIView */
prev_layer.videoGravity = AVLayerVideoGravityResize;
prev_layer.frame = strm->render_view.bounds;
[strm->render_view.layer addSublayer:prev_layer];
strm->prev_layer = prev_layer;
strm->prev_layer = [[AVCaptureVideoPreviewLayer alloc]
initWithSession:strm->cap_session];
strm->prev_layer.videoGravity =
AVLayerVideoGravityResizeAspectFill;
/* Create preview view and init it at smaller size than
* the actual video.
*/
if (!strm->prev_view) {
CGRect rect;
rect = CGRectMake(0, 0, strm->param.fmt.det.vid.size.w/2,
strm->param.fmt.det.vid.size.h/2);
strm->prev_view = [[UIView alloc] initWithFrame:rect];
}
/* Add the preview layer as sublayer */
strm->prev_layer.frame = strm->prev_view.bounds;
[strm->prev_view.layer addSublayer:strm->prev_layer];
});
PJ_LOG(4, (THIS_FILE, "Native preview initialized"));
#endif
return PJ_SUCCESS;
}
#endif
/* Fast switch */
case PJMEDIA_VID_DEV_CAP_SWITCH:
@ -1198,8 +1210,6 @@ static pj_status_t darwin_stream_set_cap(pjmedia_vid_dev_stream *s,
r.size = CGSizeMake(strm->param.disp_size.w,
strm->param.disp_size.h);
strm->render_view.bounds = r;
if (strm->prev_layer)
strm->prev_layer.frame = r;
});
return PJ_SUCCESS;
}
@ -1450,6 +1460,15 @@ static pj_status_t darwin_stream_destroy(pjmedia_vid_dev_stream *strm)
[stream->render_view release];
stream->render_view = nil;
}
if (stream->prev_view) {
[stream->prev_view
performSelectorOnMainThread:@selector(removeFromSuperview)
withObject:nil waitUntilDone:YES];
[stream->prev_view release];
stream->prev_view = nil;
}
if (stream->render_data_provider) {
CGDataProviderRelease(stream->render_data_provider);

View File

@ -255,6 +255,7 @@ PJ_DEF(pj_status_t) pjmedia_vid_conf_create(
/* Create own pool */
pool = pj_pool_create(parent_pool->factory, "vidconf", 500, 500, NULL);
if (!pool) {
PJ_PERROR(1, (THIS_FILE, PJ_ENOMEM, "Create failed in alloc"));
return PJ_ENOMEM;
}
@ -275,6 +276,7 @@ PJ_DEF(pj_status_t) pjmedia_vid_conf_create(
pj_pool_zalloc(pool, vid_conf->opt.max_slot_cnt *
sizeof(vconf_port*));
if (!vid_conf->ports) {
PJ_PERROR(1, (THIS_FILE, PJ_ENOMEM, "Create failed in alloc ports"));
pjmedia_vid_conf_destroy(vid_conf);
return PJ_ENOMEM;
}
@ -282,6 +284,7 @@ PJ_DEF(pj_status_t) pjmedia_vid_conf_create(
/* Create mutex */
status = pj_mutex_create_recursive(pool, CONF_NAME, &vid_conf->mutex);
if (status != PJ_SUCCESS) {
PJ_PERROR(1, (THIS_FILE, status, "Create failed in create mutex"));
pjmedia_vid_conf_destroy(vid_conf);
return status;
}
@ -293,6 +296,7 @@ PJ_DEF(pj_status_t) pjmedia_vid_conf_create(
status = pjmedia_clock_create2(pool, &clock_param, 0, &on_clock_tick,
vid_conf, &vid_conf->clock);
if (status != PJ_SUCCESS) {
PJ_PERROR(1, (THIS_FILE, status, "Create failed in create clock"));
pjmedia_vid_conf_destroy(vid_conf);
return status;
}
@ -301,6 +305,7 @@ PJ_DEF(pj_status_t) pjmedia_vid_conf_create(
vid_conf->op_queue = PJ_POOL_ZALLOC_T(pool, op_entry);
vid_conf->op_queue_free = PJ_POOL_ZALLOC_T(pool, op_entry);
if (!vid_conf->op_queue || !vid_conf->op_queue_free) {
PJ_PERROR(1, (THIS_FILE, PJ_ENOMEM, "Create failed in create queues"));
pjmedia_vid_conf_destroy(vid_conf);
return PJ_ENOMEM;
}
@ -310,7 +315,7 @@ PJ_DEF(pj_status_t) pjmedia_vid_conf_create(
/* Done */
*p_vid_conf = vid_conf;
PJ_LOG(5,(THIS_FILE, "Created video conference bridge with %d ports",
PJ_LOG(4,(THIS_FILE, "Created video conference bridge with %d ports",
vid_conf->opt.max_slot_cnt));
return PJ_SUCCESS;
@ -354,7 +359,7 @@ PJ_DEF(pj_status_t) pjmedia_vid_conf_destroy(pjmedia_vid_conf *vid_conf)
pj_pool_safe_release(&vid_conf->pool);
}
PJ_LOG(5,(THIS_FILE, "Video conference bridge destroyed"));
PJ_LOG(4,(THIS_FILE, "Video conference bridge destroyed"));
return PJ_SUCCESS;
}
@ -375,6 +380,8 @@ PJ_DEF(pj_status_t) pjmedia_vid_conf_add_port( pjmedia_vid_conf *vid_conf,
unsigned index;
pj_status_t status = PJ_SUCCESS;
PJ_LOG(5,(THIS_FILE, "Add port %s requested", port->info.name.ptr));
PJ_ASSERT_RETURN(vid_conf && parent_pool && port, PJ_EINVAL);
PJ_ASSERT_RETURN(port->info.fmt.type==PJMEDIA_TYPE_VIDEO &&
port->info.fmt.detail_type==PJMEDIA_FORMAT_DETAIL_VIDEO,
@ -388,6 +395,7 @@ PJ_DEF(pj_status_t) pjmedia_vid_conf_add_port( pjmedia_vid_conf *vid_conf,
pj_mutex_lock(vid_conf->mutex);
if (vid_conf->port_cnt >= vid_conf->opt.max_slot_cnt) {
PJ_PERROR(3,(THIS_FILE, PJ_ETOOMANY, "Add port %s failed", name->ptr));
pj_assert(!"Too many ports");
pj_mutex_unlock(vid_conf->mutex);
return PJ_ETOOMANY;
@ -457,7 +465,7 @@ PJ_DEF(pj_status_t) pjmedia_vid_conf_add_port( pjmedia_vid_conf *vid_conf,
vfi = pjmedia_get_video_format_info(NULL, port->info.fmt.id);
if (!vfi) {
PJ_LOG(4,(THIS_FILE, "pjmedia_vid_conf_add_port(): "
PJ_LOG(3,(THIS_FILE, "pjmedia_vid_conf_add_port(): "
"unrecognized format %04X",
port->info.fmt.id));
status = PJMEDIA_EBADFMT;
@ -468,7 +476,7 @@ PJ_DEF(pj_status_t) pjmedia_vid_conf_add_port( pjmedia_vid_conf *vid_conf,
vafp.size = port->info.fmt.det.vid.size;
status = (*vfi->apply_fmt)(vfi, &vafp);
if (status != PJ_SUCCESS) {
PJ_LOG(4,(THIS_FILE, "pjmedia_vid_conf_add_port(): "
PJ_LOG(3,(THIS_FILE, "pjmedia_vid_conf_add_port(): "
"Failed to apply format %04X",
port->info.fmt.id));
goto on_error;
@ -482,7 +490,7 @@ PJ_DEF(pj_status_t) pjmedia_vid_conf_add_port( pjmedia_vid_conf *vid_conf,
cport->put_buf,
cport->put_buf_size);
if (status != PJ_SUCCESS) {
PJ_PERROR(4,(THIS_FILE, status,
PJ_PERROR(3,(THIS_FILE, status,
"Warning: failed to init sink buffer "
" with black"));
}
@ -496,7 +504,7 @@ PJ_DEF(pj_status_t) pjmedia_vid_conf_add_port( pjmedia_vid_conf *vid_conf,
cport->get_buf,
cport->get_buf_size);
if (status != PJ_SUCCESS) {
PJ_PERROR(4,(THIS_FILE, status,
PJ_PERROR(3,(THIS_FILE, status,
"Warning: failed to init source buffer "
"with black"));
}
@ -564,6 +572,8 @@ on_error:
if (pool)
pj_pool_release(pool);
PJ_PERROR(3, (THIS_FILE, status, "Add port %s failed", name->ptr));
pj_mutex_unlock(vid_conf->mutex);
return status;
}
@ -578,6 +588,8 @@ PJ_DEF(pj_status_t) pjmedia_vid_conf_remove_port( pjmedia_vid_conf *vid_conf,
vconf_port *cport;
op_entry *ope;
PJ_LOG(5,(THIS_FILE, "Port %d remove requested", slot));
PJ_ASSERT_RETURN(vid_conf && slot<vid_conf->opt.max_slot_cnt, PJ_EINVAL);
pj_mutex_lock(vid_conf->mutex);
@ -585,11 +597,12 @@ PJ_DEF(pj_status_t) pjmedia_vid_conf_remove_port( pjmedia_vid_conf *vid_conf,
/* Port must be valid. */
cport = vid_conf->ports[slot];
if (cport == NULL) {
PJ_PERROR(3, (THIS_FILE, PJ_EINVAL, "Remove port failed"));
pj_mutex_unlock(vid_conf->mutex);
return PJ_EINVAL;
}
PJ_LOG(5,(THIS_FILE, "Video port %d remove requested", slot));
PJ_LOG(4,(THIS_FILE, "Video port %d remove queued", slot));
/* Queue the operation */
ope = get_free_op_entry(vid_conf);
@ -646,7 +659,7 @@ static void op_remove_port(pjmedia_vid_conf *vid_conf,
/* Warning: will stuck if this is called from the clock thread */
status = pjmedia_clock_stop(vid_conf->clock);
if (status != PJ_SUCCESS) {
PJ_PERROR(4, (THIS_FILE, status, "Failed to stop clock"));
PJ_PERROR(3, (THIS_FILE, status, "Failed to stop clock"));
}
}
}
@ -741,6 +754,9 @@ PJ_DEF(pj_status_t) pjmedia_vid_conf_connect_port(
vconf_port *src_port, *dst_port;
unsigned i;
PJ_LOG(5,(THIS_FILE, "Connect ports %d->%d requested",
src_slot, sink_slot));
/* Check arguments */
PJ_ASSERT_RETURN(vid_conf &&
src_slot<vid_conf->opt.max_slot_cnt &&
@ -755,7 +771,7 @@ PJ_DEF(pj_status_t) pjmedia_vid_conf_connect_port(
if (!src_port || !src_port->port->get_frame ||
!dst_port || !dst_port->port->put_frame)
{
PJ_LOG(4,(THIS_FILE,"Failed connecting video ports, make sure that "
PJ_LOG(3,(THIS_FILE,"Failed connecting video ports, make sure that "
"source has get_frame() & sink has put_frame()"));
pj_mutex_unlock(vid_conf->mutex);
return PJ_EINVAL;
@ -771,7 +787,7 @@ PJ_DEF(pj_status_t) pjmedia_vid_conf_connect_port(
if (i == src_port->listener_cnt) {
op_entry *ope;
PJ_LOG(5,(THIS_FILE, "Video connect ports %d->%d requested",
PJ_LOG(4,(THIS_FILE, "Video connect ports %d->%d queued",
src_slot, sink_slot));
ope = get_free_op_entry(vid_conf);
@ -786,7 +802,7 @@ PJ_DEF(pj_status_t) pjmedia_vid_conf_connect_port(
pj_status_t status;
status = pjmedia_clock_start(vid_conf->clock);
if (status != PJ_SUCCESS) {
PJ_PERROR(4, (THIS_FILE, status, "Failed to start clock"));
PJ_PERROR(2, (THIS_FILE, status, "Failed to start clock"));
pj_mutex_unlock(vid_conf->mutex);
return status;
}
@ -848,6 +864,9 @@ PJ_DEF(pj_status_t) pjmedia_vid_conf_disconnect_port(
vconf_port *src_port, *dst_port;
unsigned i, j;
PJ_LOG(5,(THIS_FILE, "Disconnect ports %d->%d requested",
src_slot, sink_slot));
/* Check arguments */
PJ_ASSERT_RETURN(vid_conf &&
src_slot<vid_conf->opt.max_slot_cnt &&
@ -859,6 +878,9 @@ PJ_DEF(pj_status_t) pjmedia_vid_conf_disconnect_port(
src_port = vid_conf->ports[src_slot];
dst_port = vid_conf->ports[sink_slot];
if (!src_port || !dst_port) {
PJ_PERROR(3,(THIS_FILE, PJ_EINVAL,
"Disconnect ports failed, src=0x%p dst=0x%p",
src_port, dst_port));
pj_mutex_unlock(vid_conf->mutex);
return PJ_EINVAL;
}
@ -874,24 +896,26 @@ PJ_DEF(pj_status_t) pjmedia_vid_conf_disconnect_port(
}
if (i != src_port->listener_cnt && j != dst_port->transmitter_cnt) {
op_entry *ope;
pj_assert(src_port->listener_cnt > 0 &&
src_port->listener_cnt < vid_conf->opt.max_slot_cnt);
pj_assert(dst_port->transmitter_cnt > 0 &&
dst_port->transmitter_cnt < vid_conf->opt.max_slot_cnt);
/* Queue the operation */
if (i == src_port->listener_cnt) {
op_entry *ope;
PJ_LOG(4,(THIS_FILE, "Video disconnect ports %d->%d queued",
src_slot, sink_slot));
PJ_LOG(5,(THIS_FILE, "Video disconnect ports %d->%d requested",
src_slot, sink_slot));
ope = get_free_op_entry(vid_conf);
ope->type = OP_DISCONNECT_PORTS;
ope->param.disconnect_ports.src = src_slot;
ope->param.disconnect_ports.sink = sink_slot;
pj_list_push_back(vid_conf->op_queue, ope);
}
ope = get_free_op_entry(vid_conf);
ope->type = OP_DISCONNECT_PORTS;
ope->param.disconnect_ports.src = src_slot;
ope->param.disconnect_ports.sink = sink_slot;
pj_list_push_back(vid_conf->op_queue, ope);
} else {
PJ_PERROR(3,(THIS_FILE, PJ_EINVAL,
"Disconnect ports failed, src=0x%p dst=0x%p",
src_port, dst_port));
}
pj_mutex_unlock(vid_conf->mutex);
@ -1467,6 +1491,8 @@ PJ_DEF(pj_status_t) pjmedia_vid_conf_update_port( pjmedia_vid_conf *vid_conf,
vconf_port *cport;
op_entry *ope;
PJ_LOG(5,(THIS_FILE, "Update port %d requested", slot));
PJ_ASSERT_RETURN(vid_conf && slot<vid_conf->opt.max_slot_cnt, PJ_EINVAL);
pj_mutex_lock(vid_conf->mutex);
@ -1474,6 +1500,7 @@ PJ_DEF(pj_status_t) pjmedia_vid_conf_update_port( pjmedia_vid_conf *vid_conf,
/* Port must be valid. */
cport = vid_conf->ports[slot];
if (cport == NULL) {
PJ_PERROR(3,(THIS_FILE, PJ_EINVAL, "Update port failed"));
pj_mutex_unlock(vid_conf->mutex);
return PJ_EINVAL;
}
@ -1484,6 +1511,7 @@ PJ_DEF(pj_status_t) pjmedia_vid_conf_update_port( pjmedia_vid_conf *vid_conf,
ope->param.update_port.port = slot;
pj_list_push_back(vid_conf->op_queue, ope);
PJ_LOG(4,(THIS_FILE, "Update port %d queued", slot));
pj_mutex_unlock(vid_conf->mutex);
return PJ_SUCCESS;
@ -1602,6 +1630,7 @@ static void op_update_port(pjmedia_vid_conf *vid_conf,
/* Update cport format info */
cport->format = *new_fmt;
PJ_LOG(4,(THIS_FILE, "Port %d updated", slot));
}

View File

@ -442,6 +442,7 @@ typedef enum pj_stun_status
\endverbatim
*/
#pragma pack(1)
typedef struct pj_stun_msg_hdr
{
/**
@ -473,6 +474,7 @@ typedef struct pj_stun_msg_hdr
pj_uint8_t tsx_id[12];
} pj_stun_msg_hdr;
#pragma pack()
/**
@ -490,6 +492,7 @@ typedef struct pj_stun_msg_hdr
\endverbatim
*/
#pragma pack(1)
typedef struct pj_stun_attr_hdr
{
/**
@ -506,6 +509,7 @@ typedef struct pj_stun_attr_hdr
pj_uint16_t length;
} pj_stun_attr_hdr;
#pragma pack()
/**

View File

@ -746,7 +746,7 @@ PJ_DEF(int) pj_stun_set_padding_char(int chr)
#define INIT_ATTR(a,t,l) (a)->hdr.type=(pj_uint16_t)(t), \
(a)->hdr.length=(pj_uint16_t)(l)
#define ATTR_HDR_LEN 4
#define ATTR_HDR_LEN sizeof(pj_stun_attr_hdr)
static pj_uint16_t GETVAL16H(const pj_uint8_t *buf, unsigned pos)
{
@ -1438,12 +1438,12 @@ static pj_status_t decode_uint_attr(pj_pool_t *pool,
attr = PJ_POOL_ZALLOC_T(pool, pj_stun_uint_attr);
GETATTRHDR(buf, &attr->hdr);
attr->value = GETVAL32H(buf, 4);
/* Check that the attribute length is valid */
if (attr->hdr.length != 4)
return PJNATH_ESTUNINATTRLEN;
attr->value = GETVAL32H(buf, 4);
/* Done */
*p_attr = attr;
@ -1757,14 +1757,15 @@ static pj_status_t decode_errcode_attr(pj_pool_t *pool,
attr = PJ_POOL_ZALLOC_T(pool, pj_stun_errcode_attr);
GETATTRHDR(buf, &attr->hdr);
/* Check that the attribute length is valid */
if (attr->hdr.length < 4)
return PJNATH_ESTUNINATTRLEN;
attr->err_code = buf[6] * 100 + buf[7];
/* Get pointer to the string in the message */
value.ptr = ((char*)buf + ATTR_HDR_LEN + 4);
value.slen = attr->hdr.length - 4;
/* Make sure the length is never negative */
if (value.slen < 0)
value.slen = 0;
/* Copy the string to the attribute */
pj_strdup(pool, &attr->reason, &value);
@ -2327,6 +2328,14 @@ PJ_DEF(pj_status_t) pj_stun_msg_decode(pj_pool_t *pool,
status = pj_stun_msg_check(pdu, pdu_len, options);
if (status != PJ_SUCCESS)
return status;
} else {
/* For safety, verify packet length at least */
pj_uint32_t msg_len = GETVAL16H(pdu, 2) + 20;
if (msg_len > pdu_len ||
((options & PJ_STUN_IS_DATAGRAM) && msg_len != pdu_len))
{
return PJNATH_EINSTUNMSGLEN;
}
}
/* Create the message, copy the header, and convert to host byte order */
@ -2345,7 +2354,7 @@ PJ_DEF(pj_status_t) pj_stun_msg_decode(pj_pool_t *pool,
p_response = NULL;
/* Parse attributes */
while (pdu_len >= 4) {
while (pdu_len >= ATTR_HDR_LEN) {
unsigned attr_type, attr_val_len;
const struct attr_desc *adesc;
@ -2357,7 +2366,7 @@ PJ_DEF(pj_status_t) pj_stun_msg_decode(pj_pool_t *pool,
attr_val_len = (attr_val_len + 3) & (~3);
/* Check length */
if (pdu_len < attr_val_len) {
if (pdu_len < attr_val_len + ATTR_HDR_LEN) {
pj_str_t err_msg;
char err_msg_buf[80];

View File

@ -354,37 +354,30 @@ void displayWindow(pjsua_vid_win_id wid)
for (;i < last; ++i) {
pjsua_vid_win_info wi;
if (pjsua_vid_win_get_info(i, &wi) == PJ_SUCCESS) {
if (pjsua_vid_win_get_info(i, &wi) == PJ_SUCCESS &&
wi.hwnd.info.ios.window)
{
dispatch_async(dispatch_get_main_queue(), ^{
UIView *parent = app.viewController.view;
UIView *view = (__bridge UIView *)wi.hwnd.info.ios.window;
if (view) {
/* Add the video window as subview */
if (![view isDescendantOfView:parent])
[parent addSubview:view];
if (!wi.is_native) {
/* Resize it to fit width */
view.bounds = CGRectMake(0, 0, parent.bounds.size.width,
(parent.bounds.size.height *
1.0*parent.bounds.size.width/
view.bounds.size.width));
/* Center it horizontally */
view.center = CGPointMake(parent.bounds.size.width/2.0,
view.bounds.size.height/2.0);
} else {
/* Preview window, move it to the bottom */
view.center = CGPointMake(parent.bounds.size.width/2.0,
parent.bounds.size.height-
view.bounds.size.height/2.0);
}
if (![view isDescendantOfView:parent])
[parent addSubview:view];
if (!wi.is_native) {
/* Video window */
view.contentMode = UIViewContentModeScaleAspectFit;
view.center = parent.center;
view.frame = parent.bounds;
} else {
/* Preview window */
view.contentMode = UIViewContentModeBottomLeft;
view.frame = CGRectMake(0, parent.frame.size.height - view.frame.size.height,
view.frame.size.width, view.frame.size.height);
}
});
}
}
#endif
}

View File

@ -705,11 +705,14 @@ static pj_status_t create_vid_win(pjsua_vid_win_type type,
}
}
status = pjsua_vid_conf_connect(w->cap_slot, w->rend_slot, NULL);
if (status != PJ_SUCCESS) {
PJ_PERROR(4, (THIS_FILE, status,
"Ignored error on connecting video ports "
"on wid=%d", wid));
if (!w->is_native) {
status = pjsua_vid_conf_connect(w->cap_slot, w->rend_slot,
NULL);
if (status != PJ_SUCCESS) {
PJ_PERROR(4, (THIS_FILE, status,
"Ignored error on connecting video ports "
"on wid=%d", wid));
}
}
/* Done */
@ -1700,7 +1703,7 @@ PJ_DEF(pj_status_t) pjsua_vid_win_get_info( pjsua_vid_win_id wid,
if (w->is_native) {
pjmedia_vid_dev_stream *cap_strm;
pjmedia_vid_dev_cap cap = PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW;
pjmedia_vid_dev_cap cap = PJMEDIA_VID_DEV_CAP_INPUT_PREVIEW;
if (!w->vp_cap) {
status = PJ_EINVAL;

View File

@ -1,7 +1,7 @@
# Don't change the "export PJ_VERSION_xxx" style, they are parsed by setup.py
export PJ_VERSION_MAJOR := 2
export PJ_VERSION_MINOR := 13
export PJ_VERSION_REV :=
export PJ_VERSION_REV := 1
export PJ_VERSION_SUFFIX :=
export PJ_VERSION := $(PJ_VERSION_MAJOR).$(PJ_VERSION_MINOR)