static size_t
gst_curl_smtp_sink_transfer_data_buffer (GstCurlBaseSink * bcsink,
    void *curl_ptr, size_t block_size, guint * last_chunk)
{
  GstCurlSmtpSink *sink = GST_CURL_SMTP_SINK (bcsink);
  size_t bytes_to_send;

  if (sink->payload_headers && sink->payload_headers->len) {
    return transfer_payload_headers (sink, curl_ptr, block_size);
  }

  if (sink->base64_chunk != NULL) {
    bytes_to_send =
        transfer_chunk (curl_ptr, bcsink->transfer_buf, sink->base64_chunk,
        block_size, last_chunk);

    /* if last chunk of current buffer and max attachments per mail is reached
     * then add final boundary */
    if (*last_chunk && sink->curr_attachment == sink->nbr_attachments &&
        !sink->final_boundary_added) {
      add_final_boundary_unlocked (sink);
      /* now that we've added the final boundary to the array we have on more
       * chunk to send */
      *last_chunk = 0;
    }

    GST_OBJECT_LOCK (sink);
    if (sink->eos) {
      gst_curl_smtp_sink_notify_transfer_end_unlocked (sink);
    }
    GST_OBJECT_UNLOCK (sink);

    return bytes_to_send;
  }

  /* we should never get here */
  return 0;
}
static gboolean
gst_curl_smtp_sink_event (GstBaseSink * bsink, GstEvent * event)
{
  GstCurlBaseSink *bcsink = GST_CURL_BASE_SINK (bsink);
  GstCurlSmtpSink *sink = GST_CURL_SMTP_SINK (bsink);

  switch (event->type) {
    case GST_EVENT_EOS:
      GST_DEBUG_OBJECT (sink, "received EOS");
      gst_curl_base_sink_set_live (bcsink, FALSE);

      GST_OBJECT_LOCK (sink);
      sink->eos = TRUE;
      GST_OBJECT_UNLOCK (sink);

      if (sink->base64_chunk != NULL)
        add_final_boundary_unlocked (sink);

      gst_curl_base_sink_transfer_thread_notify_unlocked (bcsink);

      GST_OBJECT_LOCK (sink);
      if (sink->base64_chunk != NULL && bcsink->flow_ret == GST_FLOW_OK) {
        gst_curl_smtp_sink_wait_for_transfer_end_unlocked (sink);
      }
      GST_OBJECT_UNLOCK (sink);

      gst_curl_base_sink_transfer_thread_close (bcsink);

      break;

    default:
      break;
  }

  return GST_BASE_SINK_CLASS (parent_class)->event (bsink, event);
}
static size_t
gst_curl_smtp_sink_flush_data_unlocked (GstCurlBaseSink * bcsink,
    void *curl_ptr, size_t block_size, gboolean new_file,
    gboolean close_transfer)
{
  GstCurlSmtpSink *sink = GST_CURL_SMTP_SINK (bcsink);
  Base64Chunk *chunk = sink->base64_chunk;
  gint state = chunk->state;
  gint save = chunk->save;
  GByteArray *array = chunk->chunk_array;
  size_t bytes_to_send;
  gint len;
  gchar *data_out;

  GST_DEBUG ("live: %d, num attachments: %d, num attachments_left: %d, eos: %d, "
      "close_transfer: %d, final boundary: %d, array_len: %d", bcsink->is_live,
      sink->nbr_attachments, sink->nbr_attachments_left, sink->eos, close_transfer,
      sink->final_boundary_added, array->len);


  if ((bcsink->is_live && (sink->nbr_attachments_left == sink->nbr_attachments))
      || (sink->nbr_attachments == 1) || sink->eos || sink->final_boundary_added) {
    bcsink->is_live = FALSE;
    sink->reset_transfer_options = TRUE;
    sink->final_boundary_added = FALSE;

    GST_DEBUG ("returning 0, no more data to send in this transfer");

    return 0;
  }

  /* it will need up to 5 bytes if line-breaking is enabled, however an
   * additional byte is needed for <CR> as it is not automatically added by glib */
  data_out = g_malloc (6);
  len = g_base64_encode_close (TRUE, data_out, &state, &save);
  chunk->state = state;
  chunk->save = save;
  /* workaround */
  data_out[len - 1] = '\r';
  data_out[len] = '\n';
  /* +1 for CR */
  g_byte_array_append (array, (guint8 *) data_out, (guint) (len + 1));
  g_free (data_out);

  if (new_file) {
    sink->nbr_attachments_left--;

    bcsink->is_live = TRUE;
    if (sink->nbr_attachments_left <= 1) {
      sink->nbr_attachments_left = sink->nbr_attachments;
    }

    /* reset flag */
    bcsink->new_file = FALSE;

    /* set payload headers for new file */
    gst_curl_smtp_sink_set_payload_headers_unlocked (bcsink);
  }


  if (close_transfer && !sink->final_boundary_added)
    add_final_boundary_unlocked (sink);

  bytes_to_send = MIN (block_size, array->len);
  memcpy ((guint8 *) curl_ptr, array->data, bytes_to_send);
  g_byte_array_remove_range (array, 0, bytes_to_send);

  return bytes_to_send;
}