Example #1
0
static void _handle_stream_start(char *name, char **attrs, 
                                 void * const userdata)
{
    xmpp_conn_t *conn = (xmpp_conn_t *)userdata;
    char *id;

    if (strcmp(name, "stream:stream") != 0) {
        printf("name = %s\n", name);
        xmpp_error(conn->ctx, "conn", "Server did not open valid stream.");
        conn_disconnect(conn);
    } else {
        _log_open_tag(conn, attrs);
        
        if (conn->stream_id) xmpp_free(conn->ctx, conn->stream_id);

        id = _get_stream_attribute(attrs, "id");
        if (id)
            conn->stream_id = xmpp_strdup(conn->ctx, id);

        if (!conn->stream_id) {
            xmpp_error(conn->ctx, "conn", "Memory allocation failed.");
            conn_disconnect(conn);
        }
    }
    
    /* call stream open handler */
    conn->open_handler(conn);
}
Example #2
0
int conn_init( conn_t *conn )
{
	char *proxy = conn->conf->http_proxy, *host = conn->conf->no_proxy;
	int i;
	
	if( *conn->conf->http_proxy == 0 )
	{
		proxy = NULL;
	}
	else if( *conn->conf->no_proxy != 0 )
	{
		for( i = 0; ; i ++ )
			if( conn->conf->no_proxy[i] == 0 )
			{
				if( strstr( conn->host, host ) != NULL )
					proxy = NULL;
				host = &conn->conf->no_proxy[i+1];
				if( conn->conf->no_proxy[i+1] == 0 )
					break;
			}
	}
	
	conn->proxy = proxy != NULL;
	
	if( conn->proto == PROTO_FTP && !conn->proxy )
	{
		conn->ftp->local_if = conn->local_if;
		conn->ftp->ftp_mode = FTP_PASSIVE;
		if( !ftp_connect( conn->ftp, conn->host, conn->port, conn->user, conn->pass ) )
		{
			conn->message = conn->ftp->message;
			conn_disconnect( conn );
			return( 0 );
		}
		conn->message = conn->ftp->message;
		if( !ftp_cwd( conn->ftp, conn->dir ) )
		{
			conn_disconnect( conn );
			return( 0 );
		}
	}
	else
	{
		conn->http->local_if = conn->local_if;
		if( !http_connect( conn->http, conn->proto, proxy, conn->host, conn->port, conn->user, conn->pass ) )
		{
			conn->message = conn->http->headers;
			conn_disconnect( conn );
			return( 0 );
		}
		conn->message = conn->http->headers;
		conn->fd = conn->http->fd;
	}
	return( 1 );
}
Example #3
0
void *search_speedtest( void *r )
{
  struct sigaction actions;
  memset(&actions, 0, sizeof(actions)); 
  sigemptyset(&actions.sa_mask);
  actions.sa_flags = 0; 
  actions.sa_handler = thread_exit_handler;
   sigaction(SIGUSR1,&actions,NULL);

	search_t *results = r;
	conn_t conn[1];
//	int oldstate;
	
	/* Allow this thread to be killed at any time.			*/
//	pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, &oldstate );
//	pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate );
	
	memset( conn, 0, sizeof( conn_t ) );
	conn->conf = results->conf;
	if( !conn_set( conn, results->url ) )
		results->speed = SPEED_ERROR;
	else if( !conn_init( conn ) )
		results->speed = SPEED_ERROR;
	else if( !conn_info( conn ) )
		results->speed = SPEED_ERROR;
	else if( conn->size == results->size )
		/* Add one because it mustn't be zero			*/
		results->speed = 1 + 1000 * ( gettime() - results->speed_start_time );
	else
		results->speed = SPEED_ERROR;

	conn_disconnect( conn );
	
	return( NULL );
}
Example #4
0
void *search_speedtest( void *r )
{
    search_t *results = r;
    conn_t conn[1];
    int oldstate;
    
    /* Allow this thread to be killed at any time.            */
    pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, &oldstate );
    pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate );
    
    memset( conn, 0, sizeof( conn_t ) );
    conn->conf = results->conf;
    if( !conn_set( conn, results->url ) )
        results->speed = SPEED_ERROR;
    else if( !conn_init( conn ) )
        results->speed = SPEED_ERROR;
    else if( !conn_info( conn ) )
        results->speed = SPEED_ERROR;
    else if( conn->size == results->size )
        /* Add one because it mustn't be zero            */
        results->speed = 1 + 1000 * ( gettime() - results->speed_start_time );
    else
        results->speed = SPEED_ERROR;

    conn_disconnect( conn );
    
    return( NULL );
}
Example #5
0
/** Cleanly disconnect the connection.
 *  This function is only called by the stream parser when </stream:stream>
 *  is received, and it not intended to be called by code outside of Strophe.
 *
 *  @param conn a Strophe connection object
 */
void conn_disconnect_clean(xmpp_conn_t * const conn)
{
    /* remove the timed handler */
    xmpp_timed_handler_delete(conn, _disconnect_cleanup);

    conn_disconnect(conn);
}
Example #6
0
File: axel.c Project: ghuntley/axel
/* Thread used to set up a connection					*/
void *setup_thread( void *c )
{
	conn_t *conn = c;
	int oldstate;
	
	/* Allow this thread to be killed at any time.			*/
	pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, &oldstate );
	pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate );
	
	if( conn_setup( conn ) )
	{
		conn->last_transfer = gettime();
		if( conn_exec( conn ) )
		{
			conn->last_transfer = gettime();
			conn->enabled = 1;
			conn->state = 0;
			return( NULL );
		}
	}
	
	conn_disconnect( conn );
	conn->state = 0;
	return( NULL );
}
Example #7
0
/* Close an axel connection */
void axel_close(axel_t *axel)
{
	int i;
	message_t *m;
	/* Terminate any thread still running */
	for (i = 0; i < axel->conf->num_connections; i++) 
	{
		/* don't try to kill non existing thread */
#if WIN32
		if (NULL != axel->conn[i].setup_thread) 
		{
			TerminateThread(axel->conn[i].setup_thread, 0);
			CloseHandle(axel->conn[i].setup_thread);
		}
#else
		if (*axel->conn[i].setup_thread != 0) 
		{
			pthread_cancel(*axel->conn[i].setup_thread);
		}
#endif
	}
	
	/* Delete state file if necessary */
	if (1 == axel->ready)
	{
		snprintf(buffer, MAX_STRING, "%s.st", axel->filename);
		unlink(buffer);
	}
	/* Else: Create it.. 						*/
	else if(axel->bytes_done > 0)
	{
		save_state(axel);
	}

	/* Delete any message not processed yet				*/
	while (axel->message)
	{
		m = axel->message;
		axel->message = axel->message->next;
		free(m);
	}
	
	/* Close all connections and local file				*/
#if WIN32
	CloseHandle(axel->outfd);
#else
	close(axel->outfd);
#endif
	for (i = 0; i < axel->conf->num_connections; i++) 
	{
		conn_disconnect(&axel->conn[i]);
	}

	free(axel->conn);
	free(axel);
#if WIN32
	WSACleanup();
#endif
}
Example #8
0
/* timed handler for cleanup if normal disconnect procedure takes too long */
static int _disconnect_cleanup(xmpp_conn_t * const conn,
			       void * const userdata)
{
	xmpp_debug(conn->ctx, "xmpp", "disconnection forced by cleanup timeout");
	conn_disconnect(conn);

	return 0;
}
Example #9
0
void __connmgr_remove_connection_at(struct conn_manager* self, size_t i)
{
        conn_disconnect(self->conns[i]);
        conn_free(self->conns[i]), free(self->conns[i]);
        size_t j;
        for (j = i + 1; j < connmgr_size(self); j ++) {
                self->conns[j - 1] = self->conns[j];
        }
        self->num_conns --;
}
Example #10
0
void connmgr_free(struct conn_manager* self)
{
        size_t i;
        for (i = 0; i < connmgr_size(self); i ++) {
                conn_disconnect(self->conns[i]);
                conn_free(self->conns[i]), free(self->conns[i]);
        }
        free(self->conns);
        memset(self, 0, sizeof(*self));
}
Example #11
0
int netserver_drop(NETSERVER *s, int client_id, const char *reason)
{
	/* TODO: insert lots of checks here */
	NETADDR addr;
	netserver_client_addr(s, client_id, &addr);
	
	dbg_msg("net_server", "client dropped. cid=%d ip=%d.%d.%d.%d reason=\"%s\"",
		client_id,
		addr.ip[0], addr.ip[1], addr.ip[2], addr.ip[3],
		reason
		);
	conn_disconnect(&s->slots[client_id].conn, reason);

	if(s->del_client)
		s->del_client(client_id, s->user_ptr);
		
	return 0;
}
Example #12
0
/* Called when tcp connection is established. */
void conn_established(xmpp_conn_t * const conn)
{
    if (conn->tls_legacy_ssl && !conn->is_raw) {
        xmpp_debug(conn->ctx, "xmpp", "using legacy SSL connection");
        if (conn_tls_start(conn) != 0) {
            conn_disconnect(conn);
            return;
        }
    }

    if (conn->is_raw) {
        handler_reset_timed(conn, 0);
        /* we skip authentication for a "raw" connection, but the event loop
           ignores user's handlers when conn->authenticated is not set. */
        conn->authenticated = 1;
        conn->conn_handler(conn, XMPP_CONN_RAW_CONNECT, 0, NULL, conn->userdata);
    } else {
        /* send stream init */
        conn_open_stream(conn);
    }
}
int netserver_drop(NETSERVER *s, int client_id, const char *reason)
{
	/* TODO: insert lots of checks here */
	NETADDR addr;
	netserver_client_addr(s, client_id, &addr);
	
	dbg_msg("Client", "Player:  %s  Disconnected.",server_clientname(client_id));

	dbg_msg("Client", "Cid: %d Disconnected. IP: %d.%d.%d.%d reason: \"%s\"",
		client_id,
		addr.ip[0], addr.ip[1], addr.ip[2], addr.ip[3],
		reason
		);

	if(s->del_client)
		s->del_client(client_id, s->user_ptr);
	conn_disconnect(&s->slots[client_id].conn, reason);


		
	return 0;
}
Example #14
0
void *setup_thread_cb( void *c )
#endif
{
	conn_t *conn = c;
	int oldstate;
	
	/* Allow this thread to be killed at any time.			*/
#if !WIN32
	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate);
#endif
	
	if (conn_setup(conn))
	{
		conn->last_transfer = gettime();
		if (conn_exec(conn))
		{
			conn->last_transfer = gettime();
			conn->enabled = 1;
			conn->state = 0;
#if WIN32
			return 0;
#else
			return NULL;
#endif
		}
	}
	
	conn_disconnect(conn);
	conn->state = 0;
#if WIN32
	return 0;
#else
	return NULL;
#endif
}
Example #15
0
int search_makelist( search_t *results, char *url )
{
	int i, size = 8192, j = 0;
	char *s, *s1, *s2, *s3;
	conn_t conn[1];
	double t;
	
	memset( conn, 0, sizeof( conn_t ) );
	
	conn->conf = results->conf;
	t = gettime();
	if( !conn_set( conn, url ) )
		return( -1 );
	if( !conn_init( conn ) )
		return( -1 );
	if( !conn_info( conn ) )
		return( -1 );
	
	strcpy( results[0].url, url );
	results[0].speed = 1 + 1000 * ( gettime() - t );
	results[0].size = conn->size;
	
	s = malloc( size );
	
	sprintf( s, "http://www.filesearching.com/cgi-bin/s?q=%s&w=a&l=en&"
		"t=f&e=on&m=%i&o=n&s1=%lld&s2=%lld&x=15&y=15",
		conn->file, results->conf->search_amount,
		conn->size, conn->size );
	
	conn_disconnect( conn );
	memset( conn, 0, sizeof( conn_t ) );
	conn->conf = results->conf;
	
	if( !conn_set( conn, s ) )
	{
		free( s );
		return( 1 );
	}
	if( !conn_setup( conn ) )
	{
		free( s );
		return( 1 );
	}
	if( !conn_exec( conn ) )
	{
		free( s );
		return( 1 );
	}
	
	while( ( i = read( conn->fd, s + j, size - j ) ) > 0 )
	{
		j += i;
		if( j + 10 >= size )
		{
			size *= 2;
			s = realloc( s, size );
			memset( s + size / 2, 0, size / 2 );
		}
	}

	conn_disconnect( conn );
	
	s1 = strstr( s, "<pre class=list" );
	s1 = strchr( s1, '\n' ) + 1;
	if( strstr( s1, "</pre>" ) == NULL )
	{
		/* Incomplete list					*/
		free( s );
		return( 1 );
	}
	for( i = 1; strncmp( s1, "</pre>", 6 ) && i < results->conf->search_amount && *s1; i ++ )
	{
		s3 = strchr( s1, '\n' ); *s3 = 0;
		s2 = strrstr( s1, "<a href=" ) + 8;
		*s3 = '\n';
		s3 = strchr( s2, ' ' ); *s3 = 0;
		if( strcmp( results[0].url, s2 ) )
		{
			strncpy( results[i].url, s2, MAX_STRING );
			results[i].size = results[0].size;
			results[i].conf = results->conf;
		}
		else
		{
			/* The original URL might show up		*/
			i --;
		}
		for( s1 = s3; *s1 != '\n'; s1 ++ );
		s1 ++;
	}
	
	free( s );
	
	return( i );
}
Example #16
0
/* authenticate the connection
 * this may get called multiple times.  if any auth method fails,
 * this will get called again until one auth method succeeds or every
 * method fails
 */
static void _auth(xmpp_conn_t * const conn)
{
    xmpp_stanza_t *auth, *authdata, *query, *child, *iq;
    char *str, *authid;
    char *scram_init;
    int anonjid;

    /* if there is no node in conn->jid, we assume anonymous connect */
    str = xmpp_jid_node(conn->ctx, conn->jid);
    if (str == NULL) {
	anonjid = 1;
    } else {
	xmpp_free(conn->ctx, str);
	anonjid = 0;
    }

    if (conn->tls_support) {
	tls_t *tls = tls_new(conn->ctx, conn->sock, conn->certfail_handler, conn->tls_cert_path);

	/* If we couldn't init tls, it isn't there, so go on */
	if (!tls) {
	    conn->tls_support = 0;
	    _auth(conn);
	    return;
	} else {
	    tls_free(tls);
	}

	auth = _make_starttls(conn);

	if (!auth) {
	    disconnect_mem_error(conn);
	    return;
	}

	handler_add(conn, _handle_proceedtls_default,
		    XMPP_NS_TLS, NULL, NULL, NULL);

	xmpp_send(conn, auth);
	xmpp_stanza_release(auth);

	/* TLS was tried, unset flag */
	conn->tls_support = 0;
	/* _auth() will be called later */
	return;
    }

    if (conn->tls_mandatory && !xmpp_conn_is_secured(conn)) {
        xmpp_error(conn->ctx, "xmpp", "TLS is not supported, but set as "
                                      "mandatory for this connection");
        conn_disconnect(conn);
        return;
    }

    if (anonjid && conn->sasl_support & SASL_MASK_ANONYMOUS) {
	/* some crap here */
	auth = _make_sasl_auth(conn, "ANONYMOUS");
	if (!auth) {
	    disconnect_mem_error(conn);
	    return;
	}

	handler_add(conn, _handle_sasl_result, XMPP_NS_SASL,
	            NULL, NULL, "ANONYMOUS");

	xmpp_send(conn, auth);
	xmpp_stanza_release(auth);

	/* SASL ANONYMOUS was tried, unset flag */
	conn->sasl_support &= ~SASL_MASK_ANONYMOUS;
    } else if (anonjid) {
	xmpp_error(conn->ctx, "auth",
		   "No node in JID, and SASL ANONYMOUS unsupported.");
	xmpp_disconnect(conn);
    } else if (conn->sasl_support & SASL_MASK_SCRAMSHA1) {
        auth = _make_sasl_auth(conn, "SCRAM-SHA-1");
        if (!auth) {
            disconnect_mem_error(conn);
            return;
        }

        /* don't free scram_init on success */
        scram_init = _make_scram_sha1_init_msg(conn);
        if (!scram_init) {
            xmpp_stanza_release(auth);
            disconnect_mem_error(conn);
            return;
        }

        str = xmpp_base64_encode(conn->ctx, (unsigned char *)scram_init,
                                 strlen(scram_init));
        if (!str) {
            xmpp_free(conn->ctx, scram_init);
            xmpp_stanza_release(auth);
            disconnect_mem_error(conn);
            return;
        }

        authdata = xmpp_stanza_new(conn->ctx);
        if (!authdata) {
            xmpp_free(conn->ctx, str);
            xmpp_free(conn->ctx, scram_init);
            xmpp_stanza_release(auth);
            disconnect_mem_error(conn);
            return;
        }
        xmpp_stanza_set_text(authdata, str);
        xmpp_free(conn->ctx, str);
        xmpp_stanza_add_child(auth, authdata);
        xmpp_stanza_release(authdata);

        handler_add(conn, _handle_scram_sha1_challenge,
                    XMPP_NS_SASL, NULL, NULL, (void *)scram_init);

        xmpp_send(conn, auth);
        xmpp_stanza_release(auth);

        /* SASL SCRAM-SHA-1 was tried, unset flag */
        conn->sasl_support &= ~SASL_MASK_SCRAMSHA1;
    } else if (conn->sasl_support & SASL_MASK_DIGESTMD5) {
	auth = _make_sasl_auth(conn, "DIGEST-MD5");
	if (!auth) {
	    disconnect_mem_error(conn);
	    return;

	}

	handler_add(conn, _handle_digestmd5_challenge,
		    XMPP_NS_SASL, NULL, NULL, NULL);

	xmpp_send(conn, auth);
	xmpp_stanza_release(auth);

	/* SASL DIGEST-MD5 was tried, unset flag */
	conn->sasl_support &= ~SASL_MASK_DIGESTMD5;
    } else if (conn->sasl_support & SASL_MASK_PLAIN) {
	auth = _make_sasl_auth(conn, "PLAIN");
	if (!auth) {
	    disconnect_mem_error(conn);
	    return;
	}
	authdata = xmpp_stanza_new(conn->ctx);
	if (!authdata) {
	    disconnect_mem_error(conn);
	    return;
	}
	authid = _get_authid(conn);
	if (!authid) {
	    disconnect_mem_error(conn);
	    return;
	}
	str = sasl_plain(conn->ctx, authid, conn->pass);
	if (!str) {
	    disconnect_mem_error(conn);
	    return;
	}
	xmpp_stanza_set_text(authdata, str);
	xmpp_free(conn->ctx, str);
	xmpp_free(conn->ctx, authid);

	xmpp_stanza_add_child(auth, authdata);
	xmpp_stanza_release(authdata);

	handler_add(conn, _handle_sasl_result,
		    XMPP_NS_SASL, NULL, NULL, "PLAIN");

	xmpp_send(conn, auth);
	xmpp_stanza_release(auth);

	/* SASL PLAIN was tried */
	conn->sasl_support &= ~SASL_MASK_PLAIN;
    } else if (conn->type == XMPP_CLIENT) {
	/* legacy client authentication */

	iq = xmpp_stanza_new(conn->ctx);
	if (!iq) {
	    disconnect_mem_error(conn);
	    return;
	}
	xmpp_stanza_set_name(iq, "iq");
	xmpp_stanza_set_type(iq, "set");
	xmpp_stanza_set_id(iq, "_xmpp_auth1");

	query = xmpp_stanza_new(conn->ctx);
	if (!query) {
	    xmpp_stanza_release(iq);
	    disconnect_mem_error(conn);
	    return;
	}
	xmpp_stanza_set_name(query, "query");
	xmpp_stanza_set_ns(query, XMPP_NS_AUTH);
	xmpp_stanza_add_child(iq, query);
	xmpp_stanza_release(query);

	child = xmpp_stanza_new(conn->ctx);
	if (!child) {
	    xmpp_stanza_release(iq);
	    disconnect_mem_error(conn);
	    return;
	}
	xmpp_stanza_set_name(child, "username");
	xmpp_stanza_add_child(query, child);
	xmpp_stanza_release(child);

	authdata = xmpp_stanza_new(conn->ctx);
	if (!authdata) {
	    xmpp_stanza_release(iq);
	    disconnect_mem_error(conn);
	    return;
	}
	str = xmpp_jid_node(conn->ctx, conn->jid);
	xmpp_stanza_set_text(authdata, str);
	xmpp_free(conn->ctx, str);
	xmpp_stanza_add_child(child, authdata);
	xmpp_stanza_release(authdata);

	child = xmpp_stanza_new(conn->ctx);
	if (!child) {
	    xmpp_stanza_release(iq);
	    disconnect_mem_error(conn);
	    return;
	}
	xmpp_stanza_set_name(child, "password");
	xmpp_stanza_add_child(query, child);
	xmpp_stanza_release(child);

	authdata = xmpp_stanza_new(conn->ctx);
	if (!authdata) {
	    xmpp_stanza_release(iq);
	    disconnect_mem_error(conn);
	    return;
	}
	xmpp_stanza_set_text(authdata, conn->pass);
	xmpp_stanza_add_child(child, authdata);
	xmpp_stanza_release(authdata);

	child = xmpp_stanza_new(conn->ctx);
	if (!child) {
	    xmpp_stanza_release(iq);
	    disconnect_mem_error(conn);
	    return;
	}
	xmpp_stanza_set_name(child, "resource");
	xmpp_stanza_add_child(query, child);
	xmpp_stanza_release(child);

	authdata = xmpp_stanza_new(conn->ctx);
	if (!authdata) {
	    xmpp_stanza_release(iq);
	    disconnect_mem_error(conn);
	    return;
	}
	str = xmpp_jid_resource(conn->ctx, conn->jid);
	if (str) {
	    xmpp_stanza_set_text(authdata, str);
	    xmpp_free(conn->ctx, str);
	} else {
	    xmpp_stanza_release(authdata);
	    xmpp_stanza_release(iq);
	    xmpp_error(conn->ctx, "auth",
		       "Cannot authenticate without resource");
	    xmpp_disconnect(conn);
	    return;
	}
	xmpp_stanza_add_child(child, authdata);
	xmpp_stanza_release(authdata);

	handler_add_id(conn, _handle_legacy, "_xmpp_auth1", NULL);
	handler_add_timed(conn, _handle_missing_legacy,
			  LEGACY_TIMEOUT, NULL);

	xmpp_send(conn, iq);
	xmpp_stanza_release(iq);
    }
}
Example #17
0
/* Get file size and other information					*/
int conn_info( conn_t *conn )
{
	/* It's all a bit messed up.. But it works.			*/
	if( conn->proto == PROTO_FTP && !conn->proxy )
	{
		ftp_command( conn->ftp, "REST %lld", 1 );
		if( ftp_wait( conn->ftp ) / 100 == 3 ||
		    conn->ftp->status / 100 == 2 )
		{
			conn->supported = 1;
			ftp_command( conn->ftp, "REST %lld", 0 );
			ftp_wait( conn->ftp );
		}
		else
		{
			conn->supported = 0;
		}
		
		if( !ftp_cwd( conn->ftp, conn->dir ) )
			return( 0 );
		conn->size = ftp_size( conn->ftp, conn->file, MAX_REDIR );
		if( conn->size < 0 )
			conn->supported = 0;
		if( conn->size == -1 )
			return( 0 );
		else if( conn->size == -2 )
			conn->size = INT_MAX;
	}
	else
	{
		char s[MAX_STRING], *t;
		long long int i = 0;
		
		do
		{
			conn->currentbyte = 1;
			if( !conn_setup( conn ) )
				return( 0 );
			conn_exec( conn );
			conn_disconnect( conn );
			/* Code 3xx == redirect				*/
			if( conn->http->status / 100 != 3 )
				break;
			if( ( t = http_header( conn->http, "location:" ) ) == NULL )
				return( 0 );
			sscanf( t, "%1023s", s );  // Warning: truncating to MAX_STRING
			if( strstr( s, "://" ) == NULL)
			{
				sprintf( conn->http->headers, "%s%s",
					conn_url( conn ), s );
				strncpy( s, conn->http->headers, MAX_STRING );
			}
			else if( s[0] == '/' )
			{
				sprintf( conn->http->headers, "http://%s:%i%s",
					conn->host, conn->port, s );
				strncpy( s, conn->http->headers, MAX_STRING );
			}
			conn_set( conn, s );
			i ++;
		}
		while( conn->http->status / 100 == 3 && i < MAX_REDIR );
		
		if( i == MAX_REDIR )
		{
			sprintf( conn->message, _("Too many redirects.\n") );
			return( 0 );
		}
		
		conn->size = http_size( conn->http );
		if( conn->http->status == 206 && conn->size >= 0 )
		{
			conn->supported = 1;
			conn->size ++;
		}
		else if( conn->http->status == 200 || conn->http->status == 206 )
		{
			conn->supported = 0;
			conn->size = INT_MAX;
		}
		else
		{
			t = strchr( conn->message, '\n' );
			if( t == NULL )
				sprintf( conn->message, _("Unknown HTTP error.\n") );
			else
				*t = 0;
			return( 0 );
		}
	}
	
	return( 1 );
}
Example #18
0
File: axel.c Project: ghuntley/axel
/* Main 'loop'								*/
void axel_do( axel_t *axel )
{
	fd_set fds[1];
	int hifd, i, j;
	long long int size;
	struct timeval timeval[1];
	
	/* Create statefile if necessary				*/
	if( gettime() > axel->next_state )
	{
		save_state( axel );
		axel->next_state = gettime() + axel->conf->save_state_interval;
	}
	
	/* Wait for data on (one of) the connections			*/
	FD_ZERO( fds );
	hifd = 0;
	for( i = 0; i < axel->conf->num_connections; i ++ )
	{
		if( axel->conn[i].enabled )
			FD_SET( axel->conn[i].fd, fds );
		hifd = max( hifd, axel->conn[i].fd );
	}
	if( hifd == 0 )
	{
		/* No connections yet. Wait...				*/
		usleep( 100000 );
		goto conn_check;
	}
	else
	{
		timeval->tv_sec = 0;
		timeval->tv_usec = 100000;
		/* A select() error probably means it was interrupted
		   by a signal, or that something else's very wrong...	*/
		if( select( hifd + 1, fds, NULL, NULL, timeval ) == -1 )
		{
			axel->ready = -1;
			return;
		}
	}
	
	/* Handle connections which need attention			*/
	for( i = 0; i < axel->conf->num_connections; i ++ )
	if( axel->conn[i].enabled ) {
	if( FD_ISSET( axel->conn[i].fd, fds ) )
	{
		axel->conn[i].last_transfer = gettime();
		size = read( axel->conn[i].fd, buffer, axel->conf->buffer_size );
		if( size == -1 )
		{
			if( axel->conf->verbose )
			{
				axel_message( axel, _("Error on connection %i! "
					"Connection closed"), i );
			}
			axel->conn[i].enabled = 0;
			conn_disconnect( &axel->conn[i] );
			continue;
		}
		else if( size == 0 )
		{
			if( axel->conf->verbose )
			{
				/* Only abnormal behaviour if:		*/
				if( axel->conn[i].currentbyte < axel->conn[i].lastbyte && axel->size != INT_MAX )
				{
					axel_message( axel, _("Connection %i unexpectedly closed"), i );
				}
				else
				{
					axel_message( axel, _("Connection %i finished"), i );
				}
			}
			if( !axel->conn[0].supported )
			{
				axel->ready = 1;
			}
			axel->conn[i].enabled = 0;
			conn_disconnect( &axel->conn[i] );
			continue;
		}
		/* j == Bytes to go					*/
		j = axel->conn[i].lastbyte - axel->conn[i].currentbyte + 1;
		if( j < size )
		{
			if( axel->conf->verbose )
			{
				axel_message( axel, _("Connection %i finished"), i );
			}
			axel->conn[i].enabled = 0;
			conn_disconnect( &axel->conn[i] );
			size = j;
			/* Don't terminate, still stuff to write!	*/
		}
		/* This should always succeed..				*/
		lseek( axel->outfd, axel->conn[i].currentbyte, SEEK_SET );
		if( write( axel->outfd, buffer, size ) != size )
		{
			
			axel_message( axel, _("Write error!") );
			axel->ready = -1;
			return;
		}
		axel->conn[i].currentbyte += size;
		axel->bytes_done += size;
	}
	else
	{
		if( gettime() > axel->conn[i].last_transfer + axel->conf->connection_timeout )
		{
			if( axel->conf->verbose )
				axel_message( axel, _("Connection %i timed out"), i );
			conn_disconnect( &axel->conn[i] );
			axel->conn[i].enabled = 0;
		}
	} }
	
	if( axel->ready )
		return;
	
conn_check:
	/* Look for aborted connections and attempt to restart them.	*/
	for( i = 0; i < axel->conf->num_connections; i ++ )
	{
		if( !axel->conn[i].enabled && axel->conn[i].currentbyte < axel->conn[i].lastbyte )
		{
			if( axel->conn[i].state == 0 )
			{
				conn_set( &axel->conn[i], axel->url->text );
				axel->url = axel->url->next;
				/* axel->conn[i].local_if = axel->conf->interfaces->text;
				axel->conf->interfaces = axel->conf->interfaces->next; */
				if( axel->conf->verbose >= 2 )
					axel_message( axel, _("Connection %i downloading from %s:%i using interface %s"),
				        	      i, axel->conn[i].host, axel->conn[i].port, axel->conn[i].local_if );
				if( pthread_create( axel->conn[i].setup_thread, NULL, setup_thread, &axel->conn[i] ) == 0 )
				{
					axel->conn[i].state = 1;
					axel->conn[i].last_transfer = gettime();
				}
				else
				{
					axel_message( axel, _("pthread error!!!") );
					axel->ready = -1;
				}
			}
			else
			{
				if( gettime() > axel->conn[i].last_transfer + axel->conf->reconnect_delay )
				{
					pthread_cancel( *axel->conn[i].setup_thread );
					axel->conn[i].state = 0;
				}
			}
		}
	}

	/* Calculate current average speed and finish_time		*/
	axel->bytes_per_second = (int) ( (double) ( axel->bytes_done - axel->start_byte ) / ( gettime() - axel->start_time ) );
	axel->finish_time = (int) ( axel->start_time + (double) ( axel->size - axel->start_byte ) / axel->bytes_per_second );

	/* Check speed. If too high, delay for some time to slow things
	   down a bit. I think a 5% deviation should be acceptable.	*/
	if( axel->conf->max_speed > 0 )
	{
		if( (float) axel->bytes_per_second / axel->conf->max_speed > 1.05 )
			axel->delay_time += 10000;
		else if( ( (float) axel->bytes_per_second / axel->conf->max_speed < 0.95 ) && ( axel->delay_time >= 10000 ) )
			axel->delay_time -= 10000;
		else if( ( (float) axel->bytes_per_second / axel->conf->max_speed < 0.95 ) )
			axel->delay_time = 0;
		usleep( axel->delay_time );
	}
	
	/* Ready?							*/
	if( axel->bytes_done == axel->size )
		axel->ready = 1;
}
Example #19
0
/** Run the event loop once.
 *  This function will run send any data that has been queued by
 *  xmpp_send and related functions and run through the Strophe even
 *  loop a single time, and will not wait more than timeout
 *  milliseconds for events.  This is provided to support integration
 *  with event loops outside the library, and if used, should be
 *  called regularly to achieve low latency event handling.
 *
 *  @param ctx a Strophe context object
 *  @param timeout time to wait for events in milliseconds
 *
 *  @ingroup EventLoop
 */
void xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout)
{
    xmpp_connlist_t *connitem;
    xmpp_conn_t *conn;
    fd_set rfds, wfds;
    sock_t max = 0;
    int ret;
    struct timeval tv;
    xmpp_send_queue_t *sq, *tsq;
    int towrite;
    char buf[4096];
    uint64_t next;
    long usec;
    int tls_read_bytes = 0;

    if (ctx->loop_status == XMPP_LOOP_QUIT) return;
    ctx->loop_status = XMPP_LOOP_RUNNING;

    /* send queued data */
    connitem = ctx->connlist;
    while (connitem) {
	conn = connitem->conn;
	if (conn->state != XMPP_STATE_CONNECTED) {
	    connitem = connitem->next;
	    continue;
	}

	/* if we're running tls, there may be some remaining data waiting to
	 * be sent, so push that out */
	if (conn->tls) {
	    ret = tls_clear_pending_write(conn->tls);

	    if (ret < 0 && !tls_is_recoverable(tls_error(conn->tls))) {
		/* an error occured */
		xmpp_debug(ctx, "xmpp", "Send error occured, disconnecting.");
		conn->error = ECONNABORTED;
		conn_disconnect(conn);
	    }
	}

	/* write all data from the send queue to the socket */
	sq = conn->send_queue_head;
	while (sq) {
	    towrite = sq->len - sq->written;

	    if (conn->tls) {
		ret = tls_write(conn->tls, &sq->data[sq->written], towrite);

		if (ret < 0 && !tls_is_recoverable(tls_error(conn->tls))) {
		    /* an error occured */
		    conn->error = tls_error(conn->tls);
		    break;
		} else if (ret < towrite) {
		    /* not all data could be sent now */
		    if (ret >= 0) sq->written += ret;
		    break;
		}

	    } else {
		ret = sock_write(conn->sock, &sq->data[sq->written], towrite);

		if (ret < 0 && !sock_is_recoverable(sock_error())) {
		    /* an error occured */
		    conn->error = sock_error();
		    break;
		} else if (ret < towrite) {
		    /* not all data could be sent now */
		    if (ret >= 0) sq->written += ret;
		    break;
		}
	    }

	    /* all data for this queue item written, delete and move on */
	    xmpp_free(ctx, sq->data);
	    tsq = sq;
	    sq = sq->next;
	    xmpp_free(ctx, tsq);

	    /* pop the top item */
	    conn->send_queue_head = sq;
	    /* if we've sent everything update the tail */
	    if (!sq) conn->send_queue_tail = NULL;
	}

	/* tear down connection on error */
	if (conn->error) {
	    /* FIXME: need to tear down send queues and random other things
	     * maybe this should be abstracted */
	    xmpp_debug(ctx, "xmpp", "Send error occured, disconnecting.");
	    conn->error = ECONNABORTED;
	    conn_disconnect(conn);
	}

	connitem = connitem->next;
    }

    /* reset parsers if needed */
    for (connitem = ctx->connlist; connitem; connitem = connitem->next) {
	if (connitem->conn->reset_parser)
	    conn_parser_reset(connitem->conn);
    }


    /* fire any ready timed handlers, then
       make sure we don't wait past the time when timed handlers need
       to be called */
    next = handler_fire_timed(ctx);

    usec = ((next < timeout) ? next : timeout) * 1000;
    tv.tv_sec = usec / 1000000;
    tv.tv_usec = usec % 1000000;

    FD_ZERO(&rfds);
    FD_ZERO(&wfds);

    /* find events to watch */
    connitem = ctx->connlist;
    while (connitem) {
	conn = connitem->conn;

	switch (conn->state) {
	case XMPP_STATE_CONNECTING:
	    /* connect has been called and we're waiting for it to complete */
	    /* connection will give us write or error events */

	    /* make sure the timeout hasn't expired */
	    if (time_elapsed(conn->timeout_stamp, time_stamp()) <=
		conn->connect_timeout)
		FD_SET(conn->sock, &wfds);
	    else {
		conn->error = ETIMEDOUT;
		xmpp_info(ctx, "xmpp", "Connection attempt timed out.");
		conn_disconnect(conn);
	    }
	    break;
	case XMPP_STATE_CONNECTED:
	    FD_SET(conn->sock, &rfds);
	    break;
	case XMPP_STATE_DISCONNECTED:
	    /* do nothing */
	default:
	    break;
	}

	/* Check if there is something in the SSL buffer. */
	if (conn->tls) {
	    tls_read_bytes += tls_pending(conn->tls);
	}

	if (conn->state != XMPP_STATE_DISCONNECTED && conn->sock > max)
	    max = conn->sock;

	connitem = connitem->next;
    }

    /* check for events */
    if (max > 0)
        ret = select(max + 1, &rfds,  &wfds, NULL, &tv);
    else {
        if (timeout > 0)
            _sleep(timeout);
        return;
    }

    /* select errored */
    if (ret < 0) {
	if (!sock_is_recoverable(sock_error()))
	    xmpp_error(ctx, "xmpp", "event watcher internal error %d",
		       sock_error());
	return;
    }

    /* no events happened */
    if (ret == 0 && tls_read_bytes == 0) return;

    /* process events */
    connitem = ctx->connlist;
    while (connitem) {
	conn = connitem->conn;

	switch (conn->state) {
	case XMPP_STATE_CONNECTING:
	    if (FD_ISSET(conn->sock, &wfds)) {
		/* connection complete */

		/* check for error */
                ret = sock_connect_error(conn->sock);
		if (ret != 0) {
		    /* connection failed */
		    xmpp_debug(ctx, "xmpp", "connection failed, error %d", ret);
		    conn_disconnect(conn);
		    break;
		}

		conn->state = XMPP_STATE_CONNECTED;
		xmpp_debug(ctx, "xmpp", "connection successful");

        if (conn->tls_legacy_ssl) {
            xmpp_debug(ctx, "xmpp", "using legacy SSL connection");
            ret = conn_tls_start(conn);
            if (ret != 0) {
                conn_disconnect(conn);
                break;
            }
        }

		/* send stream init */
		conn_open_stream(conn);
	    }

	    break;
	case XMPP_STATE_CONNECTED:
	    if (FD_ISSET(conn->sock, &rfds) || (conn->tls && tls_pending(conn->tls))) {
		if (conn->tls) {
		    ret = tls_read(conn->tls, buf, 4096);
		} else {
		    ret = sock_read(conn->sock, buf, 4096);
		}

		if (ret > 0) {
		    ret = parser_feed(conn->parser, buf, ret);
		    if (!ret) {
			/* parse error, we need to shut down */
			/* FIXME */
			xmpp_debug(ctx, "xmpp", "parse error, disconnecting");
			conn_disconnect(conn);
		    }
		} else {
		    if (conn->tls) {
			if (!tls_is_recoverable(tls_error(conn->tls)))
			{
			    xmpp_debug(ctx, "xmpp", "Unrecoverable TLS error, %d.", tls_error(conn->tls));
			    conn->error = tls_error(conn->tls);
			    conn_disconnect(conn);
			}
		    } else {
			/* return of 0 means socket closed by server */
			xmpp_debug(ctx, "xmpp", "Socket closed by remote host.");
			conn->error = ECONNRESET;
			conn_disconnect(conn);
		    }
		}
	    }

	    break;
	case XMPP_STATE_DISCONNECTED:
	    /* do nothing */
	default:
	    break;
	}

	connitem = connitem->next;
    }

    /* fire any ready handlers */
    handler_fire_timed(ctx);
}
Example #20
0
/* Main 'loop' */
void axel_do(axel_t *axel)
{
#if WIN32
	WSAEVENT hEventObject = WSACreateEvent();
	DWORD byte;
#else
	fd_set fds[1];
	struct timeval timeval[1];
	int hifd;
#endif
	int i;
	long long int remaining, size;

	/* Create statefile if necessary */
	if (axel->next_state < gettime())
	{
		save_state(axel);
		axel->next_state = gettime() + axel->conf->save_state_interval;
	}

	/* Wait for data on (one of) the connections */
#if !WIN32
	FD_ZERO(fds);
	hifd = 0;
	for (i = 0; i < axel->conf->num_connections; i++)
	{
		if (axel->conn[i].enabled) 
		{
			FD_SET(axel->conn[i].fd, fds);
		}
		hifd = max(hifd, axel->conn[i].fd);
	}

	if (0 == hifd)
	{
#ifdef DEBUG
		printf("DEBUG no connection yet. Wait...\n");
#endif
		/* No connections yet. Wait... */
		usleep(100000);
		goto conn_check;
	}
	else
	{
		timeval->tv_sec = 0;
		timeval->tv_usec = 100000;
		/* A select() error probably means it was interrupted
		   by a signal, or that something else's very wrong...	*/
		if (-1 == select(hifd + 1, fds, NULL, NULL, timeval))
		{
			axel->ready = -1;
			return;
		}
	}
#endif

	/* Handle connections which need attention */
	for (i = 0; i < axel->conf->num_connections; i++) 
	{
		if (axel->conn[i].enabled) 
		{
#if WIN32
			if (is_readable(axel, axel->conn[i].fd, hEventObject))
#else
			if (FD_ISSET(axel->conn[i].fd, fds))
#endif
			{
				axel->conn[i].last_transfer = gettime();
#if WIN32
				memset(buffer, 0, max(MAX_STRING, axel->conf->buffer_size));
				size = recv(axel->conn[i].fd, buffer, axel->conf->buffer_size, 0);
#else
				size = read(axel->conn[i].fd, buffer, axel->conf->buffer_size);
#endif
#if WIN32
				if (SOCKET_ERROR == size)
#else
				if (-1 == size)
#endif
				{
#if !WIN32
					if (axel->conf->verbose)
					{
						axel_message( axel, _("Error on connection %i! "
							"Connection closed"), i );
					}
#endif
					axel->conn[i].enabled = 0;
					conn_disconnect(&axel->conn[i]);
					continue;
				}
				else if (0 == size)
				{
					if (axel->conf->verbose)
					{
						/* Only abnormal behaviour if: */
						if (axel->conn[i].currentbyte < axel->conn[i].lastbyte && axel->size != INT_MAX)
						{
							axel_message(axel, _("Connection %i unexpectedly closed"), i);
						}
						else
						{
							axel_message(axel, _("Connection %i finished"), i);
						}
					}
					if (!axel->conn[0].supported)
					{
						axel->ready = 1;
					}
					axel->conn[i].enabled = 0;
					conn_disconnect(&axel->conn[i]);
					continue;
				}
				/* remaining == Bytes to go */
				remaining = axel->conn[i].lastbyte - axel->conn[i].currentbyte + 1;
				if (remaining < size)
				{
					if (axel->conf->verbose)
					{
						axel_message(axel, _("Connection %i finished"), i);
					}
					axel->conn[i].enabled = 0;
					conn_disconnect(&axel->conn[i]);
					size = remaining;
					/* Don't terminate, still stuff to write!	*/
				}
				/* This should always succeed..				*/
#if WIN32
				SetFilePointer(axel->outfd, axel->conn[i].currentbyte, NULL, FILE_BEGIN);
				if (0 == WriteFile(axel->outfd, buffer, size, &byte, NULL))
#else
				lseek(axel->outfd, axel->conn[i].currentbyte, SEEK_SET);
				if (write(axel->outfd, buffer, size) != size)
#endif
				{
					axel_message(axel, _("Write error!"));
					axel->ready = -1;
					return;
				}
				axel->conn[i].currentbyte += size;
				axel->bytes_done += size;
			}
			else
			{
				if (gettime() > axel->conn[i].last_transfer + axel->conf->connection_timeout)
				{
					if (axel->conf->verbose) 
					{
						axel_message(axel, _("Connection %i timed out"), i);
					}
					conn_disconnect(&axel->conn[i]);
					axel->conn[i].enabled = 0;
				}
			}
		}
	}
	if (axel->ready) 
	{
		return;
	}
	
conn_check:
	/* Look for aborted connections and attempt to restart them. */
	for (i = 0; i < axel->conf->num_connections; i++)
	{
		if (!axel->conn[i].enabled 
            && axel->conn[i].currentbyte < axel->conn[i].lastbyte)
		{
			if (0 == axel->conn[i].state)
			{	
				// Wait for termination of this thread
#if WIN32
				WaitForSingleObject(axel->conn[i].setup_thread, INFINITE);
				CloseHandle(axel->conn[i].setup_thread);
#else
				pthread_join(*(axel->conn[i].setup_thread), NULL);
#endif	
				conn_set(&axel->conn[i], axel->url->text);
				axel->url = axel->url->next;
				if (axel->conf->verbose >= 2) 
				{
					axel_message(axel, _("Connection %i downloading from %s:%i using interface %s"), 
						i, axel->conn[i].host, axel->conn[i].port, axel->conn[i].local_if);
				}
				
				axel->conn[i].state = 1;
#if WIN32
				axel->conn[i].setup_thread = CreateThread(NULL, 0, setup_thread_cb, &axel->conn[i], 0, NULL);
				if (NULL != axel->conn[i].setup_thread) 
#else
				if (pthread_create(axel->conn[i].setup_thread, NULL, setup_thread_cb, &axel->conn[i]) == 0)
#endif
				{
					axel->conn[i].last_transfer = gettime();
				}
				else
				{
					axel_message(axel, _("thread error in axel_do!!!"));
					axel->ready = -1;
				}
			}
			else
			{
				if (gettime() > axel->conn[i].last_transfer + axel->conf->reconnect_delay)
				{
#if WIN32
					TerminateThread(axel->conn[i].setup_thread, 0);
                    CloseHandle(axel->conn[i].setup_thread);
#else
					pthread_cancel(*axel->conn[i].setup_thread);
#endif
					axel->conn[i].state = 0;
				}
			}
		}
	}

	/* Calculate current average speed and finish_time		*/
	axel->bytes_per_second = (int)((double)(axel->bytes_done - axel->start_byte) / (gettime() - axel->start_time));
	axel->finish_time = (int)(axel->start_time + (double)(axel->size - axel->start_byte) / axel->bytes_per_second);

	/* Check speed. If too high, delay for some time to slow things
	   down a bit. I think a 5% deviation should be acceptable.	*/
	if (0 < axel->conf->max_speed)
	{
		if (1.05 < (float) axel->bytes_per_second / axel->conf->max_speed) 
		{
			axel->delay_time += 10000;
		}
		else if (((float)axel->bytes_per_second / axel->conf->max_speed < 0.95) 
            && 10000 <= (axel->delay_time)) 
		{
			axel->delay_time -= 10000;
		}
		else if (((float)axel->bytes_per_second / axel->conf->max_speed < 0.95)) 
		{
			axel->delay_time = 0;
		}
		usleep(axel->delay_time);
	}
	
	/* Ready? */
	if (axel->bytes_done == axel->size) 
	{
		axel->ready = 1;
	}
}