Esempio n. 1
0
/* Garbage collection: Cleans up all nodes that are handled. Useful for
   streams because there's no reason to keep a complete packet history
   in memory. */
void xt_cleanup(struct xt_parser *xt, struct xt_node *node, int depth)
{
	struct xt_node *c, *prev;

	if (!xt || !xt->root) {
		return;
	}

	if (node == NULL) {
		xt_cleanup(xt, xt->root, depth);
		return;
	}

	if (node->flags & XT_SEEN && node == xt->root) {
		xt_free_node(xt->root);
		xt->root = xt->cur = NULL;
		/* xt->cur should be NULL already, BTW... */

		return;
	}

	/* c contains the current node, prev the previous node (or NULL).
	   I admit, this one's pretty horrible. */
	for (c = node->children, prev = NULL; c; prev = c, c = c ? c->next : node->children) {
		if (c->flags & XT_SEEN) {
			/* Remove the node from the linked list. */
			if (prev) {
				prev->next = c->next;
			} else {
				node->children = c->next;
			}

			xt_free_node(c);

			/* Since the for loop wants to get c->next, make sure
			   c points at something that exists (and that c->next
			   will actually be the next item we should check). c
			   can be NULL now, if we just removed the first item.
			   That explains the ? thing in for(). */
			c = prev;
		} else {
			/* This node can't be cleaned up yet, but maybe a
			   subnode can. */
			if (depth != 0) {
				xt_cleanup(xt, c, depth > 0 ? depth - 1 : depth);
			}
		}
	}
}
Esempio n. 2
0
static gboolean jabber_read_callback( gpointer data, gint fd, b_input_condition cond )
{
	struct im_connection *ic = data;
	struct jabber_data *jd = ic->proto_data;
	char buf[512];
	int st;
	
	if( jd->fd == -1 )
		return FALSE;
	
	if( jd->ssl )
		st = ssl_read( jd->ssl, buf, sizeof( buf ) );
	else
		st = read( jd->fd, buf, sizeof( buf ) );
	
	if( st > 0 )
	{
		/* Parse. */
		if( xt_feed( jd->xt, buf, st ) < 0 )
		{
			imcb_error( ic, "XML stream error" );
			imc_logout( ic, TRUE );
			return FALSE;
		}
		
		/* Execute all handlers. */
		if( !xt_handle( jd->xt, NULL, 1 ) )
		{
			/* Don't do anything, the handlers should have
			   aborted the connection already. */
			return FALSE;
		}
		
		if( jd->flags & JFLAG_STREAM_RESTART )
		{
			jd->flags &= ~JFLAG_STREAM_RESTART;
			jabber_start_stream( ic );
		}
		
		/* Garbage collection. */
		xt_cleanup( jd->xt, NULL, 1 );
		
		/* This is a bit hackish, unfortunately. Although xmltree
		   has nifty event handler stuff, it only calls handlers
		   when nodes are complete. Since the server should only
		   send an opening <stream:stream> tag, we have to check
		   this by hand. :-( */
		if( !( jd->flags & JFLAG_STREAM_STARTED ) && jd->xt && jd->xt->root )
		{
			if( g_strcasecmp( jd->xt->root->name, "stream:stream" ) == 0 )
			{
				jd->flags |= JFLAG_STREAM_STARTED;
				
				/* If there's no version attribute, assume
				   this is an old server that can't do SASL
				   authentication. */
				if( !sasl_supported( ic ) )
				{
					/* If there's no version= tag, we suppose
					   this server does NOT implement: XMPP 1.0,
					   SASL and TLS. */
					if( set_getbool( &ic->acc->set, "tls" ) )
					{
						imcb_error( ic, "TLS is turned on for this "
						          "account, but is not supported by this server" );
						imc_logout( ic, FALSE );
						return FALSE;
					}
					else
					{
						return jabber_init_iq_auth( ic );
					}
				}
			}
			else
			{
				imcb_error( ic, "XML stream error" );
				imc_logout( ic, TRUE );
				return FALSE;
			}
		}
	}
	else if( st == 0 || ( st < 0 && !ssl_sockerr_again( jd->ssl ) ) )
	{
		closesocket( jd->fd );
		jd->fd = -1;
		
		imcb_error( ic, "Error while reading from server" );
		imc_logout( ic, TRUE );
		return FALSE;
	}
	
	if( ssl_pending( jd->ssl ) )
		/* OpenSSL empties the TCP buffers completely but may keep some
		   data in its internap buffers. select() won't see that, but
		   ssl_pending() does. */
		return jabber_read_callback( data, fd, cond );
	else
		return TRUE;
}