Exemple #1
0
/**
 * z_transfer2_update_cond:
 * @self: ZTransfer2 instance
 *
 * This function is called after a chunk of data was transferred to update
 * the stream read/write conditions. It works based on the bits
 * stored in self->status.
 **/
static void
z_transfer2_update_cond(ZTransfer2 *self)
{
  gint i;

  z_proxy_enter(self->owner);
  for (i = 0; i <= ZT2E_MAX; i++)
    {
      if ((i & ZT2E_STACKED) == 0 || self->stacked)
        {
          z_stream_set_cond(z_transfer2_get_stream(self, i), G_IO_IN, FALSE);
          z_stream_set_cond(z_transfer2_get_stream(self, i), G_IO_OUT, FALSE);
        }
    }
  if (self->stacked)
    {
      if (!z_transfer2_get_status(self, ZT2S_EOF_SOURCE))
        {
          if (z_transfer2_buffer_empty(&self->buffers[0]) && !z_transfer2_get_status(self, ZT2S_PROXY_OUT))
            z_stream_set_cond(z_transfer2_get_stream(self, ZT2E_SOURCE), G_IO_IN, TRUE);
          else
            z_stream_set_cond(z_transfer2_get_stream(self, ZT2E_DOWN_SOURCE), G_IO_OUT, TRUE);
        }
      if (!z_transfer2_get_status(self, ZT2S_EOF_DEST))
        {
          if (z_transfer2_buffer_empty(&self->buffers[1]))
            z_stream_set_cond(z_transfer2_get_stream(self, ZT2E_DOWN_DEST), G_IO_IN, TRUE);
          else
            z_stream_set_cond(z_transfer2_get_stream(self, ZT2E_DEST), G_IO_OUT, TRUE);
        }
    }
  else
    {
      /* no stacking */
      if (!z_transfer2_get_status(self, ZT2S_EOF_SOURCE))
        {
          if ((z_transfer2_buffer_empty(&self->buffers[0]) || z_transfer2_get_status(self, ZT2S_EOF_DEST) != 0) && !z_transfer2_get_status(self, ZT2S_PROXY_OUT))
            z_stream_set_cond(z_transfer2_get_stream(self, ZT2E_SOURCE), G_IO_IN, TRUE);
          else
            z_stream_set_cond(z_transfer2_get_stream(self, ZT2E_DEST), G_IO_OUT, TRUE);
        }
    }
  z_proxy_leave(self->owner);
}
Exemple #2
0
/**
 * z_proxy_control_stream_read:
 * @stream: stream to read from
 * @cond: I/O condition which triggered this call
 * @user_data: ZProxy instance as a generic pointer
 *
 * This function is registered as the read callback for control channels
 * of stacked programs.
 **/
static gboolean
z_proxy_control_stream_read(ZStream *stream, GIOCondition cond G_GNUC_UNUSED, gpointer user_data)
{
  ZStackedProxy *stacked = (ZStackedProxy *) user_data;
  ZProxy *proxy = stacked->proxy;
  GIOStatus st;
  gboolean success = FALSE;
  ZCPCommand *request = NULL, *response = NULL;
  ZCPHeader *hdr1, *hdr2;
  guint cp_sid;
  ZProxyIface *iface = NULL;
  const gchar *fail_reason = "Unknown reason";
  gboolean result = TRUE;

  z_enter();
  g_static_mutex_lock(&stacked->destroy_lock);
  if (stacked->destroyed)
    {
      /* NOTE: this stacked proxy has already been destroyed, but a callback
         was still pending, make sure we don't come back again. Note that
         our arguments except stacked might already be freed. */
      result = FALSE;
      goto exit_unlock;
    }

  if (!stacked->control_proto)
    stacked->control_proto = z_cp_context_new(stream);

  st = z_cp_context_read(stacked->control_proto, &cp_sid, &request);
  if (st == G_IO_STATUS_AGAIN)
    goto exit_unlock;
  if (st != G_IO_STATUS_NORMAL)
    {
      /* FIXME: hack, returning FALSE should be enough but it causes
         the poll loop to spin, see bug #7219 */
      z_stream_set_cond(stream, G_IO_IN, FALSE);
      result = FALSE;
      goto exit_unlock;
    }
  
  response = z_cp_command_new("RESULT");
  if (cp_sid != 0)
    {
      fail_reason = "Non-zero session-id";
      goto error;
    }

  z_log(NULL, CORE_DEBUG, 6, "Read request from stack-control channel; request='%s'", request->command->str);
  if (strcmp(request->command->str, "SETVERDICT") == 0
     )
    {
      ZProxyStackIface *siface;
      
      iface = z_proxy_find_iface(proxy, Z_CLASS(ZProxyStackIface));
      if (!iface)
        {
          fail_reason = "Proxy does not support Stack interface";
          goto error;
        }
        
      siface = (ZProxyBasicIface *) iface;
      if (strcmp(request->command->str, "SETVERDICT") == 0)
        {
          ZVerdict verdict;

          hdr1 = z_cp_command_find_header(request, "Verdict");
          hdr2 = z_cp_command_find_header(request, "Description");
          if (!hdr1)
            {
              fail_reason = "No Verdict header in SETVERDICT request";
              goto error;
            }

	  if (strcmp(hdr1->value->str, "Z_ACCEPT") == 0)
	    verdict = Z_ACCEPT;
	  else if (strcmp(hdr1->value->str, "Z_REJECT") == 0)
            verdict = Z_REJECT;
	  else if (strcmp(hdr1->value->str, "Z_DROP") == 0)
            verdict = Z_DROP;
	  else if (strcmp(hdr1->value->str, "Z_ERROR") == 0)
	    verdict = Z_ERROR;
	  else
	    verdict = Z_UNSPEC;
          
          z_proxy_stack_iface_set_verdict(iface, verdict, hdr2 ? hdr2->value->str : NULL);
        }
    }
  else
    {
      fail_reason = "Unknown request received";
      goto error;
    }
  success = TRUE;

 error:
  z_cp_command_add_header(response, g_string_new("Status"), g_string_new(success ? "OK" : "Failure"), FALSE);
  if (!success)
    {
      z_cp_command_add_header(response, g_string_new("Fail-Reason"), g_string_new(fail_reason), FALSE);
      z_log(NULL, CORE_DEBUG, 6, "Error processing control channel request; request='%s', reason='%s'", request ? request->command->str : "None", fail_reason);
    }

  z_log(NULL, CORE_DEBUG, 6, "Responding on stack-control channel; response='%s'", response->command->str);
  if (z_cp_context_write(stacked->control_proto, 0, response) != G_IO_STATUS_NORMAL)
    {
      /* this should not have happened */
      z_log(NULL, CORE_ERROR, 1, "Internal error writing response to stack-control channel;");
      success = FALSE;
    }

  if (iface)
    z_object_unref(&iface->super);
  if (request)
    z_cp_command_free(request);
  if (response)
    z_cp_command_free(response);

 exit_unlock:
  g_static_mutex_unlock(&stacked->destroy_lock);
  z_return(result);
}