Beispiel #1
0
mulk_type_return_t close_buffer(CURL *id, const char *base_url, CURLcode err_code, long resp_code, int *file_completed)
{
#ifdef ENABLE_METALINK
	double length_double;
	off_t length, byte_downloaded = 0, byte_total = 0;
	int chunk_completed = 0, chunk_total = 0, single_chunk = 0, is_file_ok = 0;
	metalink_file_list_t *metalink;
#endif /* ENABLE_METALINK */
	int i, valid_res = 0;
	mulk_type_return_t ret = MULK_RET_OK;
	buffer_t *buffer;

	if ((i = get_buffer(id)) < 0)
		return MULK_RET_ERR;

	if (file_completed)
		*file_completed = 0;

	MULK_INFO((_("Close link #%d\n"), i));

	buffer = buffer_array + i;

#ifdef ENABLE_METALINK
	metalink = buffer->url->metalink_uri;

	if (metalink) {
		metalink->header = 0;

		if (metalink->size < 0) {
			valid_res = is_valid_response(buffer->uri, err_code, resp_code, NULL, 0);

		   	if (valid_res) {
				if (curl_easy_getinfo(id, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &length_double) == CURLE_OK)
					length = (off_t) length_double;
				else
					length = 0;

				if (length > 0) {
					metalink->size = length;

					goto Exit;
				}
				else
					valid_res = 0;
			}
		}
		else {
			single_chunk = buffer->chunk && (metalink->chunk_number == 1);
			valid_res = is_valid_response(buffer->uri, err_code, resp_code, buffer->chunk, single_chunk);
		}

		/* actual URL no more used, decrement assignement counter */
		if (buffer->used_res) {
			buffer->used_res->assigned--;
			if (buffer->used_res->assigned < 0)
				buffer->used_res->assigned = 0;
		}

		if (buffer->chunk) {
			buffer->chunk->used_res = NULL;

			if (!valid_res)
				reset_chunk(buffer->chunk);

			if (file_statistics(metalink, &chunk_completed, &chunk_total,
				&byte_downloaded, &byte_total) == MULK_RET_OK) {
				MULK_INFO((_("Downloaded %d/%d chunks, %" PRIdMAX "/%" PRIdMAX " bytes\n"), chunk_completed, chunk_total,
					(intmax_t) byte_downloaded, (intmax_t) byte_total));
			}

			is_file_ok = (chunk_completed == chunk_total);
		}

		/* remove URL that returns an error from the list of usable URLs */
		if (!valid_res && buffer->used_res)
			remove_metalink_resource(metalink, buffer->used_res);

		if (buffer->chunk && is_file_ok)
			MULK_NOTE((_("RESULT: Metalink downloaded successfully, Filename:\"%s\" Size:%" PRIdMAX "\n"),
				metalink->file->name, (intmax_t) byte_downloaded));
		else if (!is_resource_available(metalink, (metalink->size < 0)))
			MULK_NOTE((_("RESULT: Metalink error, no more usable URLs for downloading, Filename:\"%s\"\n"),
				metalink->file->name));
	}
	else
		valid_res = is_valid_response(buffer->uri, err_code, resp_code, NULL, 0);
#else /* not ENABLE_METALINK */
	valid_res = is_valid_response(buffer->uri, err_code, resp_code);
#endif /* ENABLE_METALINK */

	/* is the last chunk? */
	if (get_buffer_by_url(buffer->url, i) < 0) {
#ifdef ENABLE_METALINK
		if (metalink) {
			if (!is_file_ok && is_resource_available(metalink, (metalink->size < 0)))
				goto Exit;

			valid_res = is_file_ok;
		}
#endif /* ENABLE_METALINK */

		if (buffer->file_pt)
			fclose(buffer->file_pt);
		buffer->file_pt = NULL;

		if ((ret = filter_buffer(i, valid_res, base_url, err_code, resp_code)) == MULK_RET_OK && file_completed)
			*file_completed = 1;
	}
	
#ifdef ENABLE_METALINK
Exit:
	buffer->chunk = NULL;
	buffer->used_res = NULL;
#endif
	buffer->file_pt = NULL;
	buffer->id = NULL;
	buffer->url = NULL;
	buffer->uri = NULL;
	string_free(&buffer->filename);

	return ret;
}
Beispiel #2
0
/*
 * rad_init_send_request() must have previously been called.
 * Returns:
 *   0     The application should select on *fd with a timeout of tv before
 *         calling rad_continue_send_request again.
 *   < 0   Failure
 *   > 0   Success
 */
int
rad_continue_send_request(struct rad_handle *h, int selected, int *fd,
                          struct timeval *tv)
{
	int n, cur_srv;
	time_t now;
	struct sockaddr_in sin;

	if (h->type == RADIUS_SERVER) {
		generr(h, "denied function call");
		return (-1);
	}
	if (selected) {
		struct sockaddr_in from;
		socklen_t fromlen;

		fromlen = sizeof from;
		h->in_len = recvfrom(h->fd, h->in,
		    MSGSIZE, MSG_WAITALL, (struct sockaddr *)&from, &fromlen);
		if (h->in_len == -1) {
			generr(h, "recvfrom: %s", strerror(errno));
			return -1;
		}
		if (is_valid_response(h, h->srv, &from)) {
			h->in_len = h->in[POS_LENGTH] << 8 |
			    h->in[POS_LENGTH+1];
			h->in_pos = POS_ATTRS;
			return h->in[POS_CODE];
		}
	}

	/*
         * Scan round-robin to the next server that has some
         * tries left.  There is guaranteed to be one, or we
         * would have exited this loop by now.
	 */
	cur_srv = h->srv;
	now = time(NULL);
	if (h->servers[h->srv].num_tries >= h->servers[h->srv].max_tries) {
		/* Set next probe time for this server */
		if (h->servers[h->srv].dead_time) {
			h->servers[h->srv].is_dead = 1;
			h->servers[h->srv].next_probe = now +
			    h->servers[h->srv].dead_time;
		}
		do {
		    	h->srv++;
			if (h->srv >= h->num_servers)
				h->srv = 0;
			if (h->servers[h->srv].is_dead == 0)
			    	break;
			if (h->servers[h->srv].dead_time &&
			    h->servers[h->srv].next_probe <= now) {
			    	h->servers[h->srv].is_dead = 0;
				h->servers[h->srv].num_tries = 0;
				break;
			}
		} while (h->srv != cur_srv);

		if (h->srv == cur_srv) {
			generr(h, "No valid RADIUS responses received");
			return (-1);
		}
	}

	/* Rebind */
	if (h->bindto != h->servers[h->srv].bindto) {
	    	h->bindto = h->servers[h->srv].bindto;
		close(h->fd);
		if ((h->fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
			generr(h, "Cannot create socket: %s", strerror(errno));
			return -1;
		}
		memset(&sin, 0, sizeof sin);
		sin.sin_len = sizeof sin;
		sin.sin_family = AF_INET;
		sin.sin_addr.s_addr = h->bindto;
		sin.sin_port = 0;
		if (bind(h->fd, (const struct sockaddr *)&sin,
		    sizeof sin) == -1) {
			generr(h, "bind: %s", strerror(errno));
			close(h->fd);
			h->fd = -1;
			return (-1);
		}
	}

	if (h->out[POS_CODE] == RAD_ACCESS_REQUEST) {
		/* Insert the scrambled password into the request */
		if (h->pass_pos != 0)
			insert_scrambled_password(h, h->srv);
	}
	insert_message_authenticator(h, 0);

	if (h->out[POS_CODE] != RAD_ACCESS_REQUEST) {
		/* Insert the request authenticator into the request */
		memset(&h->out[POS_AUTH], 0, LEN_AUTH);
		insert_request_authenticator(h, 0);
	}

	/* Send the request */
	n = sendto(h->fd, h->out, h->out_len, 0,
	    (const struct sockaddr *)&h->servers[h->srv].addr,
	    sizeof h->servers[h->srv].addr);
	if (n != h->out_len)
		tv->tv_sec = 1; /* Do not wait full timeout if send failed. */
	else
		tv->tv_sec = h->servers[h->srv].timeout;
	h->servers[h->srv].num_tries++;
	tv->tv_usec = 0;
	*fd = h->fd;

	return 0;
}