2010-08-31 03:50:41 +02:00
|
|
|
/******************************************************************************
|
2010-09-01 10:52:02 +02:00
|
|
|
libprozilla - a download accelerator library
|
|
|
|
Copyright (C) 2001 Kalum Somaratna
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
2010-08-31 03:50:41 +02:00
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
/* Several connection-related routines. */
|
|
|
|
|
2010-09-01 10:52:02 +02:00
|
|
|
/* $Id$ */
|
2010-08-31 03:50:41 +02:00
|
|
|
|
|
|
|
#include "common.h"
|
|
|
|
|
|
|
|
#include "prozilla.h"
|
|
|
|
#include "connection.h"
|
|
|
|
#include "misc.h"
|
|
|
|
#include "connect.h"
|
|
|
|
#include "ftp.h"
|
|
|
|
#include "http.h"
|
|
|
|
#include "debug.h"
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
2010-09-01 10:52:02 +02:00
|
|
|
...
|
2010-08-31 03:50:41 +02:00
|
|
|
******************************************************************************/
|
|
|
|
void init_response(connection_t * connection)
|
|
|
|
{
|
|
|
|
connection->serv_ret_lines = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
2010-09-01 10:52:02 +02:00
|
|
|
This will free up the serv_ret_lines array if necessary, in order to prepare
|
|
|
|
it for the storage of the servers response.
|
2010-08-31 03:50:41 +02:00
|
|
|
******************************************************************************/
|
|
|
|
void done_with_response(connection_t * connection)
|
|
|
|
{
|
|
|
|
response_line *p, *p1;
|
|
|
|
|
|
|
|
/* Return if the array is not allocated. */
|
|
|
|
if (connection->serv_ret_lines == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
p1 = connection->serv_ret_lines;
|
|
|
|
|
|
|
|
do
|
2010-09-01 10:52:02 +02:00
|
|
|
{
|
|
|
|
p = p1;
|
|
|
|
p1 = p->next;
|
|
|
|
kfree(p);
|
|
|
|
} while (p1 != 0);
|
2010-08-31 03:50:41 +02:00
|
|
|
|
|
|
|
connection->serv_ret_lines = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
2010-09-01 10:52:02 +02:00
|
|
|
Initialises the connection and sets it with values from the runtime struct.
|
2010-08-31 03:50:41 +02:00
|
|
|
******************************************************************************/
|
|
|
|
|
2010-09-01 10:52:02 +02:00
|
|
|
connection_t * proz_connection_init(urlinfo *url, pthread_mutex_t * mutex)
|
2010-08-31 03:50:41 +02:00
|
|
|
{
|
2010-09-01 10:52:02 +02:00
|
|
|
connection_t * connection = kmalloc(sizeof(connection_t));
|
2010-08-31 03:50:41 +02:00
|
|
|
|
|
|
|
memset(connection, 0, sizeof(connection_t));
|
|
|
|
|
|
|
|
/* memcpy(&connection->u, url, sizeof(urlinfo));*/
|
2010-09-01 10:52:02 +02:00
|
|
|
if (url)
|
2010-08-31 03:50:41 +02:00
|
|
|
memcpy(&connection->u,
|
2010-09-01 10:52:02 +02:00
|
|
|
proz_copy_url(url),
|
|
|
|
sizeof(urlinfo));
|
2010-08-31 03:50:41 +02:00
|
|
|
|
|
|
|
/* Copy the proxy structs. */
|
|
|
|
if (libprozrtinfo.ftp_proxy)
|
2010-09-01 10:52:02 +02:00
|
|
|
{
|
|
|
|
connection->ftp_proxy = kmalloc(sizeof(proxy_info));
|
|
|
|
memcpy(connection->ftp_proxy, libprozrtinfo.ftp_proxy,
|
|
|
|
sizeof(proxy_info));
|
|
|
|
/*
|
|
|
|
connection->use_ftp_proxy = libprozrtinfo.use_ftp_proxy;
|
|
|
|
*/
|
|
|
|
}
|
2010-08-31 03:50:41 +02:00
|
|
|
|
|
|
|
if (libprozrtinfo.http_proxy)
|
2010-09-01 10:52:02 +02:00
|
|
|
{
|
|
|
|
connection->http_proxy = kmalloc(sizeof(proxy_info));
|
|
|
|
memcpy(connection->http_proxy, libprozrtinfo.http_proxy,
|
|
|
|
sizeof(proxy_info));
|
|
|
|
/*
|
|
|
|
connection->use_http_proxy = libprozrtinfo.use_http_proxy;
|
|
|
|
*/
|
|
|
|
}
|
2010-08-31 03:50:41 +02:00
|
|
|
|
|
|
|
connection->use_netrc = libprozrtinfo.use_netrc;
|
|
|
|
|
|
|
|
connection->retry = TRUE;
|
|
|
|
connection->ftp_use_pasv = libprozrtinfo.ftp_use_pasv;
|
|
|
|
connection->http_no_cache = libprozrtinfo.http_no_cache;
|
|
|
|
|
|
|
|
connection->user_agent = strdup(DEFAULT_USER_AGENT);
|
|
|
|
connection->file_mode = strdup("wb");
|
|
|
|
/*NOTE: default of unlimited attempts */
|
|
|
|
connection->max_attempts = 0;
|
|
|
|
connection->attempts = 0;
|
|
|
|
/* Initialise all with default timeouts */
|
|
|
|
memcpy(&connection->xfer_timeout, &libprozrtinfo.conn_timeout,
|
2010-09-01 10:52:02 +02:00
|
|
|
sizeof(connection->xfer_timeout));
|
2010-08-31 03:50:41 +02:00
|
|
|
memcpy(&connection->ctrl_timeout, &libprozrtinfo.conn_timeout,
|
2010-09-01 10:52:02 +02:00
|
|
|
sizeof(connection->ctrl_timeout));
|
2010-08-31 03:50:41 +02:00
|
|
|
memcpy(&connection->conn_timeout, &libprozrtinfo.conn_timeout,
|
2010-09-01 10:52:02 +02:00
|
|
|
sizeof(connection->conn_timeout));
|
2010-08-31 03:50:41 +02:00
|
|
|
memcpy(&connection->retry_delay, &libprozrtinfo.conn_retry_delay,
|
2010-09-01 10:52:02 +02:00
|
|
|
sizeof(&connection->retry_delay));
|
2010-08-31 03:50:41 +02:00
|
|
|
connection->max_attempts = libprozrtinfo.max_attempts;
|
|
|
|
|
|
|
|
connection->rate_bps = 0;
|
|
|
|
/* Unlimited bandwith (0) */
|
|
|
|
connection->max_allowed_bps = 0;
|
|
|
|
pthread_cond_init(&connection->connecting_cond, NULL);
|
|
|
|
connection->status_change_mutex = mutex;
|
|
|
|
if (connection->status_change_mutex != 0)
|
2010-09-01 10:52:02 +02:00
|
|
|
{
|
|
|
|
pthread_mutex_init(connection->status_change_mutex, NULL);
|
|
|
|
}
|
2010-08-31 03:50:41 +02:00
|
|
|
pthread_mutex_init(&connection->access_mutex, NULL);
|
|
|
|
|
|
|
|
return connection;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Locks the connections mutex befoer chaging state. */
|
|
|
|
void connection_change_status(connection_t * connection, dl_status status)
|
|
|
|
{
|
|
|
|
if (connection->status_change_mutex != 0)
|
2010-09-01 10:52:02 +02:00
|
|
|
{
|
|
|
|
pthread_mutex_lock(connection->status_change_mutex);
|
|
|
|
connection->status = status;
|
|
|
|
pthread_mutex_unlock(connection->status_change_mutex);
|
|
|
|
}
|
2010-08-31 03:50:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-09-01 10:52:02 +02:00
|
|
|
/* this will open connection->localfile and read from connection->data_sock
|
|
|
|
(which should be already setup) till a EOF is reached or
|
|
|
|
the server closes the connection, in which case there is no way to know
|
|
|
|
whether we got the complete file.
|
|
|
|
*/
|
2010-08-31 03:50:41 +02:00
|
|
|
|
|
|
|
uerr_t connection_retr_fsize_not_known(connection_t * connection,
|
2010-09-01 10:52:02 +02:00
|
|
|
char *read_buffer,
|
|
|
|
int read_buffer_size)
|
2010-08-31 03:50:41 +02:00
|
|
|
{
|
|
|
|
off_t bytes_read;
|
|
|
|
|
|
|
|
connection_change_status(connection, DOWNLOADING);
|
|
|
|
gettimeofday(&connection->time_begin, NULL);
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
2010-09-01 10:52:02 +02:00
|
|
|
bytes_read =
|
|
|
|
krecv(connection->data_sock, read_buffer, read_buffer_size, 0,
|
|
|
|
&connection->xfer_timeout);
|
|
|
|
if (bytes_read > 0)
|
|
|
|
{
|
|
|
|
if (write_data_with_lock(connection, read_buffer, sizeof(char), bytes_read) < bytes_read)
|
|
|
|
{
|
|
|
|
proz_debug(_("write failed"));
|
|
|
|
connection_show_message(connection,
|
|
|
|
_
|
|
|
|
("Unable to write to file %s: %s!"),
|
|
|
|
connection->localfile, strerror(errno));
|
|
|
|
connection_change_status(connection, LOCALFATAL);
|
|
|
|
return FWRITEERR;
|
|
|
|
}
|
|
|
|
pthread_mutex_lock(&connection->access_mutex);
|
|
|
|
connection->remote_bytes_received += bytes_read;
|
|
|
|
pthread_mutex_unlock(&connection->access_mutex);
|
|
|
|
|
|
|
|
/*TODO: caclculate and throttle connections speed here */
|
|
|
|
/*DONE: */
|
|
|
|
connection_calc_ratebps(connection);
|
|
|
|
connection_throttle_bps(connection);
|
|
|
|
}
|
|
|
|
} while (bytes_read > 0);
|
2010-08-31 03:50:41 +02:00
|
|
|
|
|
|
|
if (bytes_read == -1)
|
|
|
|
{
|
2010-09-01 10:52:02 +02:00
|
|
|
if (errno == ETIMEDOUT)
|
|
|
|
{
|
|
|
|
proz_debug(_("connection timed out"));
|
|
|
|
connection_change_status(connection, TIMEDOUT);
|
|
|
|
return READERR;
|
|
|
|
}
|
|
|
|
connection_change_status(connection, REMOTEFATAL);
|
2010-08-31 03:50:41 +02:00
|
|
|
return READERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
connection_change_status(connection, COMPLETED);
|
|
|
|
|
|
|
|
connection_show_message(connection,
|
2010-09-01 10:52:02 +02:00
|
|
|
_("download for this connection completed"
|
|
|
|
"%s : %ld received"), connection->localfile,
|
|
|
|
connection->remote_bytes_received);
|
2010-08-31 03:50:41 +02:00
|
|
|
return FILEGETOK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-09-01 10:52:02 +02:00
|
|
|
/* This will open connection->localfile and read from connection->data_sock
|
2010-08-31 03:50:41 +02:00
|
|
|
(which should be already setup) till the requested number of bytes are read.
|
2010-09-01 10:52:02 +02:00
|
|
|
Now since we explicitly know how much bytes to get we can do so, and is the server
|
|
|
|
closes the connection prematurely we know that has hapenned (because it hasn't supplied
|
2010-08-31 03:50:41 +02:00
|
|
|
the required number of bytes) and return a READERR.
|
2010-09-01 10:52:02 +02:00
|
|
|
*/
|
2010-08-31 03:50:41 +02:00
|
|
|
uerr_t connection_retr_fsize_known(connection_t * connection,
|
2010-09-01 10:52:02 +02:00
|
|
|
char *read_buffer, int read_buffer_size)
|
2010-08-31 03:50:41 +02:00
|
|
|
{
|
|
|
|
off_t bytes_read;
|
|
|
|
off_t bytes_to_get;
|
|
|
|
|
|
|
|
pthread_mutex_lock(&connection->access_mutex);
|
|
|
|
bytes_to_get = connection->remote_endpos - connection->remote_startpos;
|
|
|
|
pthread_mutex_unlock(&connection->access_mutex);
|
|
|
|
|
|
|
|
connection_change_status(connection, DOWNLOADING);
|
|
|
|
gettimeofday(&connection->time_begin, NULL);
|
|
|
|
|
|
|
|
while (bytes_to_get > 0)
|
|
|
|
{
|
2010-09-01 10:52:02 +02:00
|
|
|
bytes_read =
|
|
|
|
krecv(connection->data_sock, read_buffer,
|
|
|
|
bytes_to_get >
|
|
|
|
read_buffer_size ? read_buffer_size : bytes_to_get, 0,
|
|
|
|
&connection->xfer_timeout);
|
|
|
|
|
|
|
|
if (bytes_read == 0 && bytes_to_get > 0)
|
|
|
|
{
|
|
|
|
connection_show_message(connection,
|
|
|
|
_("Server Closed Connection Prematurely!"));
|
|
|
|
connection_change_status(connection, REMOTEFATAL);
|
|
|
|
return READERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bytes_read == -1)
|
|
|
|
{
|
|
|
|
if (errno == ETIMEDOUT)
|
|
|
|
{
|
|
|
|
proz_debug(_("connection timed out"));
|
|
|
|
connection_change_status(connection, TIMEDOUT);
|
|
|
|
return READERR;
|
|
|
|
}
|
|
|
|
connection_change_status(connection, REMOTEFATAL);
|
|
|
|
return READERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
bytes_to_get -= bytes_read;
|
|
|
|
|
|
|
|
if (bytes_read > 0)
|
|
|
|
{
|
|
|
|
if (write_data_with_lock(connection, read_buffer, sizeof(char), bytes_read) < bytes_read)
|
|
|
|
{
|
|
|
|
proz_debug(_("write failed"));
|
|
|
|
connection_show_message(connection,
|
|
|
|
_
|
|
|
|
("Unable to write to file %s: %s!"),
|
|
|
|
connection->localfile, strerror(errno));
|
|
|
|
connection_change_status(connection, LOCALFATAL);
|
|
|
|
return FWRITEERR;
|
|
|
|
}
|
|
|
|
pthread_mutex_lock(&connection->access_mutex);
|
|
|
|
connection->remote_bytes_received += bytes_read;
|
|
|
|
pthread_mutex_unlock(&connection->access_mutex);
|
|
|
|
|
|
|
|
/*TODO: caclculate and throttle connections speed here */
|
|
|
|
/*DONE: */
|
|
|
|
connection_calc_ratebps(connection);
|
|
|
|
connection_throttle_bps(connection);
|
|
|
|
}
|
2010-08-31 03:50:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
connection_change_status(connection, COMPLETED);
|
|
|
|
|
|
|
|
connection_show_message(connection,
|
2010-09-01 10:52:02 +02:00
|
|
|
_("download for this connection completed"
|
|
|
|
"%s : %ld received"), connection->localfile,
|
|
|
|
connection->remote_bytes_received);
|
2010-08-31 03:50:41 +02:00
|
|
|
return FILEGETOK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-09-01 10:52:02 +02:00
|
|
|
/* This function modifies a single connections download start and
|
|
|
|
end info it returns 1 on sucess and -1 on error.
|
|
|
|
*/
|
2010-08-31 03:50:41 +02:00
|
|
|
|
|
|
|
|
|
|
|
int connection_load_resume_info(connection_t * connection)
|
|
|
|
{
|
2010-09-01 10:52:02 +02:00
|
|
|
if (connection->remote_startpos - connection->orig_remote_startpos != connection->remote_bytes_received)
|
|
|
|
{
|
|
|
|
proz_debug("connection->remote start pos before loading %ld", connection->remote_startpos);
|
|
|
|
//connection->remote_startpos +=connection->remote_bytes_received;
|
|
|
|
connection->remote_startpos += (connection->remote_bytes_received - (connection->remote_startpos - connection->orig_remote_startpos));
|
2010-08-31 03:50:41 +02:00
|
|
|
|
2010-09-01 10:52:02 +02:00
|
|
|
proz_debug("connection->remote start pos after loading %ld", connection->remote_startpos);
|
|
|
|
}
|
2010-08-31 03:50:41 +02:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
dl_status proz_connection_get_status(connection_t * connection)
|
|
|
|
{
|
|
|
|
dl_status status;
|
2010-09-01 10:52:02 +02:00
|
|
|
|
2010-08-31 03:50:41 +02:00
|
|
|
pthread_mutex_lock(connection->status_change_mutex);
|
|
|
|
status = connection->status;
|
|
|
|
pthread_mutex_unlock(connection->status_change_mutex);
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*This will return a textual representation of the status of a conenction. */
|
|
|
|
char *proz_connection_get_status_string(connection_t * connection)
|
|
|
|
{
|
|
|
|
dl_status status;
|
2010-09-01 10:52:02 +02:00
|
|
|
|
2010-08-31 03:50:41 +02:00
|
|
|
pthread_mutex_lock(connection->status_change_mutex);
|
|
|
|
status = connection->status;
|
|
|
|
pthread_mutex_unlock(connection->status_change_mutex);
|
|
|
|
|
|
|
|
switch (connection->status)
|
2010-09-01 10:52:02 +02:00
|
|
|
{
|
|
|
|
case IDLE:
|
|
|
|
return(_("Idle"));
|
|
|
|
|
|
|
|
case CONNECTING:
|
|
|
|
return(_("Connecting"));
|
2010-08-31 03:50:41 +02:00
|
|
|
|
2010-09-01 10:52:02 +02:00
|
|
|
case LOGGININ:
|
|
|
|
return(_("Logging in"));
|
2010-08-31 03:50:41 +02:00
|
|
|
|
2010-09-01 10:52:02 +02:00
|
|
|
case DOWNLOADING:
|
|
|
|
return(_("Downloading"));
|
|
|
|
break;
|
2010-08-31 03:50:41 +02:00
|
|
|
|
2010-09-01 10:52:02 +02:00
|
|
|
case COMPLETED:
|
|
|
|
return(_("Completed"));
|
2010-08-31 03:50:41 +02:00
|
|
|
|
2010-09-01 10:52:02 +02:00
|
|
|
case LOGINFAIL:
|
|
|
|
return(_("Login Denied"));
|
2010-08-31 03:50:41 +02:00
|
|
|
|
2010-09-01 10:52:02 +02:00
|
|
|
case CONREJECT:
|
|
|
|
return(_("Connect Refused"));
|
2010-08-31 03:50:41 +02:00
|
|
|
|
2010-09-01 10:52:02 +02:00
|
|
|
case REMOTEFATAL:
|
|
|
|
return(_("Remote Fatal"));
|
2010-08-31 03:50:41 +02:00
|
|
|
|
2010-09-01 10:52:02 +02:00
|
|
|
case LOCALFATAL:
|
|
|
|
return(_("Local Fatal"));
|
2010-08-31 03:50:41 +02:00
|
|
|
|
2010-09-01 10:52:02 +02:00
|
|
|
case TIMEDOUT:
|
|
|
|
return(_("Timed Out"));
|
2010-08-31 03:50:41 +02:00
|
|
|
|
2010-09-01 10:52:02 +02:00
|
|
|
case MAXTRYS:
|
|
|
|
return(_("Max attempts reached"));
|
2010-08-31 03:50:41 +02:00
|
|
|
|
2010-09-01 10:52:02 +02:00
|
|
|
default:
|
|
|
|
return(_("Unkown Status!"));
|
|
|
|
}
|
2010-08-31 03:50:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pthread_mutex_t connection_msg_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
|
|
|
|
|
|
/*calls the msg_proc function if not null */
|
|
|
|
void connection_show_message(connection_t * connection, const char *format,
|
2010-09-01 10:52:02 +02:00
|
|
|
...)
|
2010-08-31 03:50:41 +02:00
|
|
|
{
|
|
|
|
va_list args;
|
|
|
|
char message[MAX_MSG_SIZE + 1];
|
|
|
|
|
|
|
|
pthread_mutex_lock(&connection_msg_mutex);
|
|
|
|
va_start(args, format);
|
|
|
|
vsnprintf(message, MAX_MSG_SIZE, format, args);
|
|
|
|
va_end(args);
|
|
|
|
if (connection->msg_proc)
|
|
|
|
connection->msg_proc(message, connection->cb_data);
|
|
|
|
|
|
|
|
/*FIXME: Remove this later */
|
|
|
|
// printf("%s\n", message);
|
|
|
|
pthread_mutex_unlock(&connection_msg_mutex);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Returns the total number of bytes that have been saved to the file*/
|
|
|
|
off_t proz_connection_get_total_bytes_got(connection_t * connection)
|
|
|
|
{
|
|
|
|
off_t ret;
|
|
|
|
|
|
|
|
pthread_mutex_lock(&connection->access_mutex);
|
|
|
|
ret = connection->remote_bytes_received;
|
|
|
|
pthread_mutex_unlock(&connection->access_mutex);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-09-01 10:52:02 +02:00
|
|
|
/*****************************************************************************
|
|
|
|
Returns the total number of bytes that has being got from the server
|
|
|
|
by this connection.
|
|
|
|
******************************************************************************/
|
2010-08-31 03:50:41 +02:00
|
|
|
off_t proz_connection_get_total_remote_bytes_got(connection_t * connection)
|
|
|
|
{
|
|
|
|
off_t ret;
|
2010-09-01 10:52:02 +02:00
|
|
|
|
2010-08-31 03:50:41 +02:00
|
|
|
pthread_mutex_lock(&connection->access_mutex);
|
|
|
|
ret = (connection->remote_bytes_received
|
2010-09-01 10:52:02 +02:00
|
|
|
- (connection->remote_startpos - connection->orig_remote_startpos));
|
2010-08-31 03:50:41 +02:00
|
|
|
pthread_mutex_unlock(&connection->access_mutex);
|
2010-09-01 10:52:02 +02:00
|
|
|
//proz_debug("CONNECTION TOTAL REMOTE BYTES GOT =%lld", ret);
|
2010-08-31 03:50:41 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void proz_get_url_info_loop(connection_t * connection, pthread_t *thread)
|
|
|
|
{
|
|
|
|
assert(connection);
|
|
|
|
assert(thread);
|
|
|
|
connection->running = TRUE;
|
|
|
|
pthread_create(thread, NULL,
|
2010-09-01 10:52:02 +02:00
|
|
|
(void *(*)(void *))get_url_info_loop,
|
|
|
|
(void *)connection);
|
2010-08-31 03:50:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
2010-09-01 10:52:02 +02:00
|
|
|
This Fucntion will retreive info about the given url in the connection,
|
|
|
|
handling conditions like redirection from http to ftp etc
|
2010-08-31 03:50:41 +02:00
|
|
|
|
2010-09-01 10:52:02 +02:00
|
|
|
*************************************************************************/
|
2010-08-31 03:50:41 +02:00
|
|
|
void get_url_info_loop(connection_t * connection)
|
|
|
|
{
|
|
|
|
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
|
|
|
|
|
|
|
|
/*TODO Should we try to make it broadcast a condition to the other threads? */
|
|
|
|
pthread_mutex_lock(&connection->access_mutex);
|
|
|
|
connection->running = TRUE;
|
|
|
|
pthread_mutex_unlock(&connection->access_mutex);
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
2010-09-01 10:52:02 +02:00
|
|
|
switch (connection->u.proto)
|
|
|
|
{
|
|
|
|
case URLHTTP:
|
|
|
|
connection->err = http_get_url_info_loop(connection);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case URLFTP:
|
|
|
|
connection->err = ftp_get_url_info_loop(connection);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
proz_die(_("Error: unsupported protocol"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (connection->err == NEWLOCATION)
|
|
|
|
{
|
|
|
|
char *constructed_newloc;
|
|
|
|
char *referer;
|
|
|
|
referer = kstrdup(connection->u.url);
|
|
|
|
/*DONE : handle relative urls too */
|
|
|
|
constructed_newloc =
|
|
|
|
uri_merge(connection->u.url, connection->hs.newloc);
|
|
|
|
|
|
|
|
proz_debug("Redirected to %s, merged URL = %s",
|
|
|
|
connection->hs.newloc, constructed_newloc);
|
|
|
|
|
|
|
|
proz_free_url(&connection->u, 0);
|
|
|
|
connection->err =
|
|
|
|
proz_parse_url(constructed_newloc, &connection->u, 0);
|
|
|
|
|
|
|
|
|
|
|
|
if (connection->err != URLOK)
|
|
|
|
{
|
|
|
|
connection_show_message(connection,
|
|
|
|
_
|
|
|
|
("The server returned location is wrong: %s!"),
|
|
|
|
constructed_newloc);
|
|
|
|
pthread_mutex_lock(&connection->access_mutex);
|
|
|
|
connection->running = FALSE;
|
|
|
|
pthread_mutex_unlock(&connection->access_mutex);
|
|
|
|
kfree(constructed_newloc);
|
|
|
|
connection->err = HERR;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
connection_show_message(connection, _("Redirected to => %s"),
|
|
|
|
constructed_newloc);
|
|
|
|
connection->u.referer = referer;
|
|
|
|
kfree(constructed_newloc);
|
|
|
|
connection->err = NEWLOCATION;
|
|
|
|
}
|
|
|
|
} while (connection->err == NEWLOCATION);
|
2010-08-31 03:50:41 +02:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void proz_connection_set_msg_proc(connection_t * connection,
|
2010-09-01 10:52:02 +02:00
|
|
|
message_proc msg_proc, void *cb_data)
|
2010-08-31 03:50:41 +02:00
|
|
|
{
|
|
|
|
assert(connection != NULL);
|
|
|
|
|
|
|
|
|
|
|
|
connection->msg_proc = msg_proc;
|
|
|
|
connection->cb_data = cb_data;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void connection_calc_ratebps(connection_t * connection)
|
|
|
|
{
|
|
|
|
struct timeval tv_cur;
|
|
|
|
struct timeval tv_diff;
|
|
|
|
float diff_us;
|
|
|
|
|
|
|
|
pthread_mutex_lock(&connection->access_mutex);
|
|
|
|
|
|
|
|
if (connection->time_begin.tv_sec == 0
|
|
|
|
&& connection->time_begin.tv_usec == 0)
|
2010-09-01 10:52:02 +02:00
|
|
|
{
|
|
|
|
connection->rate_bps = 0;
|
|
|
|
pthread_mutex_unlock(&connection->access_mutex);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gettimeofday(&tv_cur, NULL);
|
|
|
|
proz_timeval_subtract(&tv_diff, &tv_cur, &(connection->time_begin));
|
|
|
|
diff_us = ((float)tv_diff.tv_sec * 10e5) + tv_diff.tv_usec;
|
2010-08-31 03:50:41 +02:00
|
|
|
|
|
|
|
/* if (diff_us == 0) */
|
|
|
|
/* { */
|
|
|
|
/* pthread_mutex_unlock(&connection->access_mutex); */
|
|
|
|
/* return; */
|
|
|
|
/* } */
|
|
|
|
/* connection->rate_bps = */
|
2010-09-01 10:52:02 +02:00
|
|
|
/* ((float) (connection->remote_bytes_received */
|
|
|
|
/* - (connection->remote_startpos-connection->orig_remote_startpos)) * 10e5 / diff_us); */
|
2010-08-31 03:50:41 +02:00
|
|
|
/* } */
|
|
|
|
|
2010-09-01 10:52:02 +02:00
|
|
|
if (diff_us < 100000)
|
|
|
|
{
|
|
|
|
connection->rate_bps = 0;
|
|
|
|
pthread_mutex_unlock(&connection->access_mutex);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
connection->rate_bps =
|
|
|
|
((float)(connection->remote_bytes_received
|
|
|
|
- (connection->remote_startpos - connection->orig_remote_startpos)) * 10e5 / diff_us);
|
2010-08-31 03:50:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
pthread_mutex_unlock(&connection->access_mutex);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void connection_throttle_bps(connection_t * connection)
|
|
|
|
{
|
|
|
|
struct timeval tv_cur;
|
|
|
|
struct timeval tv_diff;
|
|
|
|
float diff_us;
|
|
|
|
float wtime;
|
|
|
|
struct timeval tv_delay;
|
|
|
|
float con_timeout_usecs;
|
|
|
|
|
|
|
|
pthread_mutex_lock(&connection->access_mutex);
|
|
|
|
|
|
|
|
con_timeout_usecs =
|
2010-09-01 10:52:02 +02:00
|
|
|
(connection->conn_timeout.tv_sec * 10e5) +
|
|
|
|
connection->conn_timeout.tv_usec;
|
2010-08-31 03:50:41 +02:00
|
|
|
|
|
|
|
if (connection->rate_bps == 0 || connection->max_allowed_bps == 0)
|
2010-09-01 10:52:02 +02:00
|
|
|
{
|
|
|
|
pthread_mutex_unlock(&connection->access_mutex);
|
|
|
|
return;
|
|
|
|
}
|
2010-08-31 03:50:41 +02:00
|
|
|
|
|
|
|
if (connection->time_begin.tv_sec == 0
|
|
|
|
&& connection->time_begin.tv_usec == 0)
|
2010-09-01 10:52:02 +02:00
|
|
|
{
|
|
|
|
pthread_mutex_unlock(&connection->access_mutex);
|
|
|
|
return;
|
|
|
|
}
|
2010-08-31 03:50:41 +02:00
|
|
|
|
|
|
|
|
|
|
|
gettimeofday(&tv_cur, NULL);
|
|
|
|
proz_timeval_subtract(&tv_diff, &tv_cur, &(connection->time_begin));
|
2010-09-01 10:52:02 +02:00
|
|
|
diff_us = ((float)tv_diff.tv_sec * 10e5) + tv_diff.tv_usec;
|
2010-08-31 03:50:41 +02:00
|
|
|
|
|
|
|
if (diff_us == 0)
|
2010-09-01 10:52:02 +02:00
|
|
|
{
|
|
|
|
pthread_mutex_unlock(&connection->access_mutex);
|
|
|
|
return;
|
|
|
|
}
|
2010-08-31 03:50:41 +02:00
|
|
|
|
|
|
|
|
|
|
|
wtime =
|
2010-09-01 10:52:02 +02:00
|
|
|
10e5 * (connection->remote_bytes_received
|
|
|
|
- (connection->remote_startpos - connection->orig_remote_startpos)) /
|
|
|
|
connection->max_allowed_bps;
|
2010-08-31 03:50:41 +02:00
|
|
|
|
|
|
|
pthread_mutex_unlock(&connection->access_mutex);
|
|
|
|
|
|
|
|
memset(&tv_delay, 0, sizeof(tv_delay));
|
|
|
|
|
|
|
|
if (wtime > diff_us)
|
|
|
|
{
|
2010-09-01 10:52:02 +02:00
|
|
|
/*too fast have to delay */
|
|
|
|
// proz_debug("wtime %f, diff_us %f", wtime, diff_us);
|
|
|
|
if ((wtime - diff_us) > con_timeout_usecs) /* problem here */
|
|
|
|
{
|
|
|
|
/*If we were to delay for wtime-diff_us we would cause a connection
|
|
|
|
timeout, so rather than doing that shall we delay for a bit lesser
|
|
|
|
than the time for the timeout, like say 1 second less
|
|
|
|
*/
|
|
|
|
const int limit_time_us = 2 * 10e5;
|
|
|
|
|
|
|
|
/* Will the connection timeout - limit_time_us be less or equal to 0?
|
|
|
|
If so no point in delaing beacuse the connection wold timeout
|
|
|
|
*/
|
|
|
|
|
|
|
|
if ((con_timeout_usecs - limit_time_us) <= 0)
|
|
|
|
{
|
|
|
|
proz_debug
|
|
|
|
("Cant throttle: Connection would timeout if done so, please try increasing the timeout value");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
tv_delay.tv_usec = con_timeout_usecs - limit_time_us;
|
|
|
|
/* message
|
|
|
|
("Cant throttle fully : Connection would timeout if done so, please try increasing the timeout value"); */
|
|
|
|
|
|
|
|
proz_debug("delaymaxlimit %ld sec\n", tv_delay.tv_usec);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tv_delay.tv_usec = (wtime - diff_us);
|
2010-08-31 03:50:41 +02:00
|
|
|
//#warning "comment out the following line before releasing the code base"
|
2010-09-01 10:52:02 +02:00
|
|
|
proz_debug("sleeping %f secs\n", (wtime - diff_us) / 10e5);
|
|
|
|
}
|
2010-08-31 03:50:41 +02:00
|
|
|
|
2010-09-01 10:52:02 +02:00
|
|
|
tv_delay.tv_sec = tv_delay.tv_usec / 1000000;
|
|
|
|
tv_delay.tv_usec = tv_delay.tv_usec % 1000000;
|
2010-08-31 03:50:41 +02:00
|
|
|
|
2010-09-01 10:52:02 +02:00
|
|
|
if (select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv_delay) < 0)
|
|
|
|
{
|
|
|
|
proz_debug("Unable to throttle Bandwith\n");
|
|
|
|
}
|
2010-08-31 03:50:41 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
boolean proz_connection_running(connection_t * connection)
|
|
|
|
{
|
|
|
|
boolean running;
|
2010-09-01 10:52:02 +02:00
|
|
|
|
2010-08-31 03:50:41 +02:00
|
|
|
pthread_mutex_lock(&connection->access_mutex);
|
|
|
|
running = connection->running;
|
|
|
|
pthread_mutex_unlock(&connection->access_mutex);
|
|
|
|
return running;
|
|
|
|
}
|
|
|
|
|
|
|
|
void proz_connection_set_url(connection_t * connection, urlinfo *url)
|
|
|
|
{
|
|
|
|
assert(url);
|
2010-09-01 10:52:02 +02:00
|
|
|
memcpy(&connection->u,
|
|
|
|
proz_copy_url(url),
|
|
|
|
sizeof(urlinfo));
|
2010-08-31 03:50:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void proz_connection_free_connection(connection_t * connection,
|
2010-09-01 10:52:02 +02:00
|
|
|
boolean complete)
|
2010-08-31 03:50:41 +02:00
|
|
|
{
|
|
|
|
assert(connection);
|
|
|
|
/*TODO what about szBuffer..also have to free the URL u */
|
|
|
|
|
|
|
|
if (connection->localfile)
|
|
|
|
kfree(connection->localfile);
|
|
|
|
if (connection->file_mode)
|
|
|
|
kfree(connection->file_mode);
|
|
|
|
if (connection->http_proxy)
|
|
|
|
kfree(connection->http_proxy);
|
|
|
|
if (connection->ftp_proxy)
|
|
|
|
kfree(connection->ftp_proxy);
|
|
|
|
|
|
|
|
if (connection->user_agent)
|
|
|
|
kfree(connection->user_agent);
|
|
|
|
|
|
|
|
/* free the serv_ret_lines array */
|
|
|
|
if (connection->serv_ret_lines != 0)
|
2010-09-01 10:52:02 +02:00
|
|
|
{
|
|
|
|
done_with_response(connection);
|
|
|
|
}
|
2010-08-31 03:50:41 +02:00
|
|
|
|
|
|
|
if (complete == TRUE)
|
|
|
|
kfree(connection);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
size_t write_data_with_lock(connection_t * connection, const void *ptr, size_t size, size_t nmemb)
|
|
|
|
{
|
|
|
|
size_t ret;
|
2010-09-01 10:52:02 +02:00
|
|
|
|
2010-08-31 03:50:41 +02:00
|
|
|
flockfile(connection->fp);
|
|
|
|
/*Seek appropriately......*/
|
|
|
|
|
2010-09-01 10:52:02 +02:00
|
|
|
ret = fseeko(connection->fp, connection->local_startpos + connection->remote_bytes_received, SEEK_SET);
|
|
|
|
ret = fwrite(ptr, size, nmemb, connection->fp);
|
2010-08-31 03:50:41 +02:00
|
|
|
|
|
|
|
funlockfile(connection->fp);
|
|
|
|
return ret;
|
|
|
|
}
|