static pj_status_t flush_circ_buf_output(pj_ssl_sock_t *ssock,
                                         pj_ioqueue_op_key_t *send_key,
                                         pj_size_t orig_len, unsigned flags)
{
    pj_ssize_t len;
    write_data_t *wdata;
    pj_size_t needed_len;
    pj_status_t status;

    pj_lock_acquire(ssock->write_mutex);

    /* Check if there is data in the circular buffer, flush it if any */
    if (io_empty(ssock, &ssock->circ_buf_output)) {
	pj_lock_release(ssock->write_mutex);
	return PJ_SUCCESS;
    }

    /* Get data and its length */
    len = io_size(ssock, &ssock->circ_buf_output);
    if (len == 0) {
	pj_lock_release(ssock->write_mutex);
	return PJ_SUCCESS;
    }

    /* Calculate buffer size needed, and align it to 8 */
    needed_len = len + sizeof(write_data_t);
    needed_len = ((needed_len + 7) >> 3) << 3;

    /* Allocate buffer for send data */
    wdata = alloc_send_data(ssock, needed_len);
    if (wdata == NULL) {
	/* Oops, the send buffer is full, let's just
	 * queue it for sending and return PJ_EPENDING.
	 */
	ssock->send_buf_pending.data_len = needed_len;
	ssock->send_buf_pending.app_key = send_key;
	ssock->send_buf_pending.flags = flags;
	ssock->send_buf_pending.plain_data_len = orig_len;
	pj_lock_release(ssock->write_mutex);
	return PJ_EPENDING;
    }

    /* Copy the data and set its properties into the send data */
    pj_ioqueue_op_key_init(&wdata->key, sizeof(pj_ioqueue_op_key_t));
    wdata->key.user_data = wdata;
    wdata->app_key = send_key;
    wdata->record_len = needed_len;
    wdata->data_len = len;
    wdata->plain_data_len = orig_len;
    wdata->flags = flags;
    io_read(ssock, &ssock->circ_buf_output, (pj_uint8_t *)&wdata->data, len);

    /* Ticket #1573: Don't hold mutex while calling PJLIB socket send(). */
    pj_lock_release(ssock->write_mutex);

    /* Send it */
#ifdef SSL_SOCK_IMP_USE_OWN_NETWORK
    status = network_send(ssock, &wdata->key, wdata->data.content, &len,
			  flags);
#else
    if (ssock->param.sock_type == pj_SOCK_STREAM()) {
	status = pj_activesock_send(ssock->asock, &wdata->key, 
				    wdata->data.content, &len,
				    flags);
    } else {
	status = pj_activesock_sendto(ssock->asock, &wdata->key, 
				      wdata->data.content, &len,
				      flags,
				      (pj_sockaddr_t*)&ssock->rem_addr,
				      ssock->addr_len);
    }
#endif

    if (status != PJ_EPENDING) {
	/* When the sending is not pending, remove the wdata from send
	 * pending list.
	 */
	pj_lock_acquire(ssock->write_mutex);
	free_send_data(ssock, wdata);
	pj_lock_release(ssock->write_mutex);
    }

    return status;
}
static pj_status_t flush_circ_buf_output(pj_ssl_sock_t *ssock,
                                         pj_ioqueue_op_key_t *send_key,
                                         pj_size_t orig_len, unsigned flags)
{
    pj_ssize_t len;
    write_data_t *wdata;
    pj_size_t needed_len;
    pj_status_t status;

    pj_lock_acquire(ssock->write_mutex);

     
    if (io_empty(ssock, &ssock->circ_buf_output)) {
	pj_lock_release(ssock->write_mutex);
	return PJ_SUCCESS;
    }

     
    len = io_size(ssock, &ssock->circ_buf_output);
    if (len == 0) {
	pj_lock_release(ssock->write_mutex);
	return PJ_SUCCESS;
    }

     
    needed_len = len + sizeof(write_data_t);
    needed_len = ((needed_len + 7) >> 3) << 3;

     
    wdata = alloc_send_data(ssock, needed_len);
    if (wdata == NULL) {
	 
	ssock->send_buf_pending.data_len = needed_len;
	ssock->send_buf_pending.app_key = send_key;
	ssock->send_buf_pending.flags = flags;
	ssock->send_buf_pending.plain_data_len = orig_len;
	pj_lock_release(ssock->write_mutex);
	return PJ_EPENDING;
    }

     
    pj_ioqueue_op_key_init(&wdata->key, sizeof(pj_ioqueue_op_key_t));
    wdata->key.user_data = wdata;
    wdata->app_key = send_key;
    wdata->record_len = needed_len;
    wdata->data_len = len;
    wdata->plain_data_len = orig_len;
    wdata->flags = flags;
    io_read(ssock, &ssock->circ_buf_output, (pj_uint8_t *)&wdata->data, len);

     
    pj_lock_release(ssock->write_mutex);

     
#ifdef SSL_SOCK_IMP_USE_OWN_NETWORK
    status = network_send(ssock, &wdata->key, wdata->data.content, &len,
			  flags);
#else
    if (ssock->param.sock_type == pj_SOCK_STREAM()) {
	status = pj_activesock_send(ssock->asock, &wdata->key, 
				    wdata->data.content, &len,
				    flags);
    } else {
	status = pj_activesock_sendto(ssock->asock, &wdata->key, 
				      wdata->data.content, &len,
				      flags,
				      (pj_sockaddr_t*)&ssock->rem_addr,
				      ssock->addr_len);
    }
#endif

    if (status != PJ_EPENDING) {
	 
	pj_lock_acquire(ssock->write_mutex);
	free_send_data(ssock, wdata);
	pj_lock_release(ssock->write_mutex);
    }

    return status;
}