mirror of
https://github.com/rkd77/elinks.git
synced 2024-12-04 14:46:47 -05:00
Bug 1013: Don't assume errno is between 0 and 100000
Replace almost all uses of enum connection_state with struct connection_status. This removes the assumption that errno values used by the system are between 0 and 100000. The GNU Hurd uses values like ENOENT = 0x40000002 and EMIG_SERVER_DIED = -308. This commit is derived from my attachments 450 and 467 to bug 1013.
This commit is contained in:
parent
40715ffbd4
commit
6c2e8cd7b2
1
NEWS
1
NEWS
@ -21,6 +21,7 @@ includes the changes listed under "ELinks 0.11.4.GIT now" below.
|
||||
JS_CallFunction, which can crash if given a closure.
|
||||
* critical bug 1031: Use the same JSRuntime for both user SMJS and
|
||||
scripts on web pages, to work around SpiderMonkey bug 378918.
|
||||
* bug 1013: Don't assume errno values are between 0 and 100000
|
||||
* bug 1022: Add connection.ssl.trusted_ca_file setting for GnuTLS.
|
||||
Before this, ELinks did not trust any certificate authorities when
|
||||
it used GnuTLS, so certificate verification always failed if you
|
||||
|
@ -132,7 +132,7 @@ download_dialog_layouter(struct dialog_data *dlg_data)
|
||||
&& download->progress->size >= 0);
|
||||
#if CONFIG_BITTORRENT
|
||||
int bittorrent = (file_download->uri->protocol == PROTOCOL_BITTORRENT
|
||||
&& (show_meter || download->state == S_RESUME));
|
||||
&& (show_meter || is_in_state(download->state, S_RESUME)));
|
||||
#endif
|
||||
|
||||
redraw_below_window(dlg_data->win);
|
||||
@ -402,7 +402,7 @@ draw_file_download(struct listbox_item *item, struct listbox_context *context,
|
||||
|
||||
if (!download->progress
|
||||
|| download->progress->size < 0
|
||||
|| download->state != S_TRANS
|
||||
|| !is_in_state(download->state, S_TRANS)
|
||||
|| !has_progress(download->progress)) {
|
||||
/* TODO: Show trimmed error message. */
|
||||
return;
|
||||
|
@ -74,7 +74,8 @@ save_url(struct session *ses, unsigned char *url)
|
||||
|
||||
uri = get_translated_uri(url, ses->tab->term->cwd);
|
||||
if (!uri) {
|
||||
print_error_dialog(ses, S_BAD_URL, uri, PRI_CANCEL);
|
||||
print_error_dialog(ses, connection_state(S_BAD_URL),
|
||||
uri, PRI_CANCEL);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -568,12 +569,14 @@ query_file(struct session *ses, struct uri *uri, void *data,
|
||||
* the checking? --jonas */
|
||||
|
||||
if (uri->protocol == PROTOCOL_UNKNOWN) {
|
||||
print_error_dialog(ses, S_UNKNOWN_PROTOCOL, uri, PRI_CANCEL);
|
||||
print_error_dialog(ses, connection_state(S_UNKNOWN_PROTOCOL),
|
||||
uri, PRI_CANCEL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (get_protocol_external_handler(ses->tab->term, uri)) {
|
||||
print_error_dialog(ses, S_EXTERNAL_PROTOCOL, uri, PRI_CANCEL);
|
||||
print_error_dialog(ses, connection_state(S_EXTERNAL_PROTOCOL),
|
||||
uri, PRI_CANCEL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -214,12 +214,12 @@ display_status_bar(struct session *ses, struct terminal *term, int tabs_count)
|
||||
static int last_current_link;
|
||||
int ncl = doc_view->vs->current_link;
|
||||
|
||||
if (download->state == S_INTERRUPTED
|
||||
if (is_in_state(download->state, S_INTERRUPTED)
|
||||
&& ncl != last_current_link)
|
||||
download->state = S_OK;
|
||||
download->state = connection_state(S_OK);
|
||||
last_current_link = ncl;
|
||||
|
||||
if (download->state == S_OK) {
|
||||
if (is_in_state(download->state, S_OK)) {
|
||||
if (get_current_link(doc_view)) {
|
||||
msg = get_current_link_info_and_title(ses, doc_view);
|
||||
} else if (ses->navigate_mode == NAVIGATE_CURSOR_ROUTING) {
|
||||
@ -340,7 +340,7 @@ display_tab_bar(struct session *ses, struct terminal *term, int tabs_count)
|
||||
} else {
|
||||
download = get_current_download(tab_ses);
|
||||
|
||||
if (download && download->state != S_OK) {
|
||||
if (download && !is_in_state(download->state, S_OK)) {
|
||||
color = loading_color;
|
||||
} else if (!tab_ses || !tab_ses->status.visited) {
|
||||
color = fresh_color;
|
||||
|
@ -94,7 +94,7 @@ import_css_file(struct css_stylesheet *css, struct uri *base_uri,
|
||||
|
||||
add_bytes_to_string(&filename, url, urllen);
|
||||
|
||||
if (read_encoded_file(&filename, &string) == S_OK) {
|
||||
if (is_in_state(read_encoded_file(&filename, &string), S_OK)) {
|
||||
unsigned char *end = string.source + string.length;
|
||||
|
||||
css->import_level++;
|
||||
|
@ -223,10 +223,10 @@ try_encoding_extensions(struct string *filename, int *fd)
|
||||
* whether the true end of the stream has been reached.
|
||||
*
|
||||
* @return a connection state. S_OK if all is well. */
|
||||
enum connection_state
|
||||
struct connection_state
|
||||
read_file(struct stream_encoded *stream, int readsize, struct string *page)
|
||||
{
|
||||
if (!init_string(page)) return S_OUT_OF_MEM;
|
||||
if (!init_string(page)) return connection_state(S_OUT_OF_MEM);
|
||||
|
||||
/* We read with granularity of stt.st_size (given as @readsize) - this
|
||||
* does best job for uncompressed files, and doesn't hurt for
|
||||
@ -248,17 +248,17 @@ read_file(struct stream_encoded *stream, int readsize, struct string *page)
|
||||
* do. Since errno == 0 == S_WAIT and we cannot have
|
||||
* that. */
|
||||
if (errno)
|
||||
return (enum connection_state) -errno;
|
||||
return connection_state_for_errno(errno);
|
||||
|
||||
/* FIXME: This is indeed an internal error. If readed from a
|
||||
* corrupted encoded file nothing or only some of the
|
||||
* data will be read. */
|
||||
return S_ENCODE_ERROR;
|
||||
return connection_state(S_ENCODE_ERROR);
|
||||
|
||||
} else if (readlen == 0) {
|
||||
/* NUL-terminate just in case */
|
||||
page->source[page->length] = '\0';
|
||||
return S_OK;
|
||||
return connection_state(S_OK);
|
||||
}
|
||||
|
||||
page->length += readlen;
|
||||
@ -276,7 +276,7 @@ read_file(struct stream_encoded *stream, int readsize, struct string *page)
|
||||
}
|
||||
|
||||
done_string(page);
|
||||
return S_OUT_OF_MEM;
|
||||
return connection_state(S_OUT_OF_MEM);
|
||||
}
|
||||
|
||||
static inline int
|
||||
@ -291,14 +291,14 @@ is_stdin_pipe(struct stat *stt, struct string *filename)
|
||||
S_ISFIFO(stt->st_mode));
|
||||
}
|
||||
|
||||
enum connection_state
|
||||
struct connection_state
|
||||
read_encoded_file(struct string *filename, struct string *page)
|
||||
{
|
||||
struct stream_encoded *stream;
|
||||
struct stat stt;
|
||||
enum stream_encoding encoding = ENCODING_NONE;
|
||||
int fd = open(filename->source, O_RDONLY | O_NOCTTY);
|
||||
enum connection_state state = -errno;
|
||||
struct connection_state state = connection_state_for_errno(errno);
|
||||
|
||||
if (fd == -1 && get_opt_bool("protocol.file.try_encoding_extensions")) {
|
||||
encoding = try_encoding_extensions(filename, &fd);
|
||||
@ -323,7 +323,7 @@ read_encoded_file(struct string *filename, struct string *page)
|
||||
/* Do all the necessary checks before trying to read the file.
|
||||
* @state code is used to block further progress. */
|
||||
if (fstat(fd, &stt)) {
|
||||
state = -errno;
|
||||
state = connection_state_for_errno(errno);
|
||||
|
||||
} else if (!S_ISREG(stt.st_mode) && encoding != ENCODING_NONE) {
|
||||
/* We only want to open regular encoded files. */
|
||||
@ -331,10 +331,10 @@ read_encoded_file(struct string *filename, struct string *page)
|
||||
|
||||
} else if (!S_ISREG(stt.st_mode) && !is_stdin_pipe(&stt, filename)
|
||||
&& !get_opt_bool("protocol.file.allow_special_files")) {
|
||||
state = S_FILE_TYPE;
|
||||
state = connection_state(S_FILE_TYPE);
|
||||
|
||||
} else if (!(stream = open_encoded(fd, encoding))) {
|
||||
state = S_OUT_OF_MEM;
|
||||
state = connection_state(S_OUT_OF_MEM);
|
||||
|
||||
} else {
|
||||
int readsize = (int) stt.st_size;
|
||||
@ -343,9 +343,9 @@ read_encoded_file(struct string *filename, struct string *page)
|
||||
/* FIXME: See bug 497 for info about support for big files. */
|
||||
if (readsize != stt.st_size || readsize < 0) {
|
||||
#ifdef EFBIG
|
||||
state = (enum connection_state) -(EFBIG);
|
||||
state = connection_state_for_errno(EFBIG);
|
||||
#else
|
||||
state = S_FILE_ERROR;
|
||||
state = connection_state(S_FILE_ERROR);
|
||||
#endif
|
||||
|
||||
} else {
|
||||
|
@ -39,10 +39,10 @@ enum stream_encoding guess_encoding(unsigned char *filename);
|
||||
const unsigned char *get_encoding_name(enum stream_encoding encoding);
|
||||
|
||||
/* Read from open @stream into the @page string */
|
||||
enum connection_state
|
||||
struct connection_state
|
||||
read_file(struct stream_encoded *stream, int readsize, struct string *page);
|
||||
|
||||
/* Reads the file with the given @filename into the string @source. */
|
||||
enum connection_state read_encoded_file(struct string *filename, struct string *source);
|
||||
struct connection_state read_encoded_file(struct string *filename, struct string *source);
|
||||
|
||||
#endif
|
||||
|
@ -228,28 +228,28 @@ check_queue_bugs(void)
|
||||
#endif
|
||||
|
||||
static void
|
||||
set_connection_socket_state(struct socket *socket, enum connection_state state)
|
||||
set_connection_socket_state(struct socket *socket, struct connection_state state)
|
||||
{
|
||||
assert(socket);
|
||||
set_connection_state(socket->conn, state);
|
||||
}
|
||||
|
||||
static void
|
||||
set_connection_socket_timeout(struct socket *socket, enum connection_state state)
|
||||
set_connection_socket_timeout(struct socket *socket, struct connection_state state)
|
||||
{
|
||||
assert(socket);
|
||||
set_connection_timeout(socket->conn);
|
||||
}
|
||||
|
||||
static void
|
||||
retry_connection_socket(struct socket *socket, enum connection_state state)
|
||||
retry_connection_socket(struct socket *socket, struct connection_state state)
|
||||
{
|
||||
assert(socket);
|
||||
retry_connection(socket->conn, state);
|
||||
}
|
||||
|
||||
static void
|
||||
done_connection_socket(struct socket *socket, enum connection_state state)
|
||||
done_connection_socket(struct socket *socket, struct connection_state state)
|
||||
{
|
||||
assert(socket);
|
||||
abort_connection(socket->conn, state);
|
||||
@ -338,7 +338,7 @@ stat_timer(struct connection *conn)
|
||||
}
|
||||
|
||||
void
|
||||
set_connection_state(struct connection *conn, enum connection_state state)
|
||||
set_connection_state(struct connection *conn, struct connection_state state)
|
||||
{
|
||||
struct download *download;
|
||||
struct progress *progress = conn->progress;
|
||||
@ -347,7 +347,7 @@ set_connection_state(struct connection *conn, enum connection_state state)
|
||||
conn->prev_error = conn->state;
|
||||
|
||||
conn->state = state;
|
||||
if (conn->state == S_TRANS) {
|
||||
if (is_in_state(conn->state, S_TRANS)) {
|
||||
if (progress->timer == TIMER_ID_UNDEF) {
|
||||
start_update_progress(progress, (void (*)(void *)) stat_timer, conn);
|
||||
update_connection_progress(conn);
|
||||
@ -412,14 +412,14 @@ free_connection_data(struct connection *conn)
|
||||
|
||||
kill_timer(&conn->timer);
|
||||
|
||||
if (conn->state != S_WAIT)
|
||||
if (!is_in_state(conn->state, S_WAIT))
|
||||
done_host_connection(conn);
|
||||
}
|
||||
|
||||
void
|
||||
notify_connection_callbacks(struct connection *conn)
|
||||
{
|
||||
enum connection_state state = conn->state;
|
||||
struct connection_state state = conn->state;
|
||||
struct download *download, *next;
|
||||
|
||||
foreachsafe (download, next, conn->downloads) {
|
||||
@ -439,7 +439,7 @@ done_connection(struct connection *conn)
|
||||
* connection is in a result state. If it is not already it is an
|
||||
* internal bug. This should never happen but it does. ;) --jonas */
|
||||
if (!is_in_result_state(conn->state))
|
||||
set_connection_state(conn, S_INTERNAL);
|
||||
set_connection_state(conn, connection_state(S_INTERNAL));
|
||||
|
||||
del_from_list(conn);
|
||||
notify_connection_callbacks(conn);
|
||||
@ -696,7 +696,7 @@ static inline void
|
||||
suspend_connection(struct connection *conn)
|
||||
{
|
||||
interrupt_connection(conn);
|
||||
set_connection_state(conn, S_WAIT);
|
||||
set_connection_state(conn, connection_state(S_WAIT));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -710,7 +710,7 @@ run_connection(struct connection *conn)
|
||||
if_assert_failed return;
|
||||
|
||||
if (!add_host_connection(conn)) {
|
||||
set_connection_state(conn, S_OUT_OF_MEM);
|
||||
set_connection_state(conn, connection_state(S_OUT_OF_MEM));
|
||||
done_connection(conn);
|
||||
return;
|
||||
}
|
||||
@ -723,12 +723,12 @@ run_connection(struct connection *conn)
|
||||
|
||||
/* Set certain state on a connection and then abort the connection. */
|
||||
void
|
||||
abort_connection(struct connection *conn, enum connection_state state)
|
||||
abort_connection(struct connection *conn, struct connection_state state)
|
||||
{
|
||||
assertm(is_in_result_state(state),
|
||||
"connection didn't end in result state (%d)", state);
|
||||
|
||||
if (state == S_OK && conn->cached)
|
||||
if (is_in_state(state, S_OK) && conn->cached)
|
||||
normalize_cache_entry(conn->cached, conn->from);
|
||||
|
||||
set_connection_state(conn, state);
|
||||
@ -740,7 +740,7 @@ abort_connection(struct connection *conn, enum connection_state state)
|
||||
|
||||
/* Set certain state on a connection and then retry the connection. */
|
||||
void
|
||||
retry_connection(struct connection *conn, enum connection_state state)
|
||||
retry_connection(struct connection *conn, struct connection_state state)
|
||||
{
|
||||
int max_tries = get_opt_int("connection.retries");
|
||||
|
||||
@ -767,7 +767,7 @@ try_to_suspend_connection(struct connection *conn, struct uri *uri)
|
||||
|
||||
foreachback (c, connection_queue) {
|
||||
if (get_priority(c) <= priority) return -1;
|
||||
if (c->state == S_WAIT) continue;
|
||||
if (is_in_state(c->state, S_WAIT)) continue;
|
||||
if (c->uri->post && get_priority(c) < PRI_CANCEL) continue;
|
||||
if (uri && !compare_uri(uri, c->uri, URI_HOST)) continue;
|
||||
suspend_connection(c);
|
||||
@ -812,7 +812,8 @@ again:
|
||||
struct connection *cc = c;
|
||||
|
||||
c = c->next;
|
||||
if (cc->state == S_WAIT && get_keepalive_connection(cc)
|
||||
if (is_in_state(cc->state, S_WAIT)
|
||||
&& get_keepalive_connection(cc)
|
||||
&& try_connection(cc, max_conns_to_host, max_conns))
|
||||
goto again;
|
||||
}
|
||||
@ -821,7 +822,7 @@ again:
|
||||
struct connection *cc = c;
|
||||
|
||||
c = c->next;
|
||||
if (cc->state == S_WAIT
|
||||
if (is_in_state(cc->state, S_WAIT)
|
||||
&& try_connection(cc, max_conns_to_host, max_conns))
|
||||
goto again;
|
||||
}
|
||||
@ -831,8 +832,8 @@ again:
|
||||
again2:
|
||||
foreachback (conn, connection_queue) {
|
||||
if (get_priority(conn) < PRI_CANCEL) break;
|
||||
if (conn->state == S_WAIT) {
|
||||
set_connection_state(conn, S_INTERRUPTED);
|
||||
if (is_in_state(conn->state, S_WAIT)) {
|
||||
set_connection_state(conn, connection_state(S_INTERRUPTED));
|
||||
done_connection(conn);
|
||||
goto again2;
|
||||
}
|
||||
@ -854,14 +855,14 @@ load_uri(struct uri *uri, struct uri *referrer, struct download *download,
|
||||
struct cache_entry *cached;
|
||||
struct connection *conn;
|
||||
struct uri *proxy_uri, *proxied_uri;
|
||||
enum connection_state connection_state = S_OK;
|
||||
struct connection_state error_state = connection_state(S_OK);
|
||||
|
||||
if (download) {
|
||||
download->conn = NULL;
|
||||
download->cached = NULL;
|
||||
download->pri = pri;
|
||||
download->state = S_OUT_OF_MEM;
|
||||
download->prev_error = 0;
|
||||
download->state = connection_state(S_OUT_OF_MEM);
|
||||
download->prev_error = connection_state(0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG
|
||||
@ -871,7 +872,7 @@ load_uri(struct uri *uri, struct uri *referrer, struct download *download,
|
||||
foreach (assigned, conn->downloads) {
|
||||
assertm(assigned != download, "Download assigned to '%s'", struri(conn->uri));
|
||||
if_assert_failed {
|
||||
download->state = S_INTERNAL;
|
||||
download->state = connection_state(S_INTERNAL);
|
||||
if (download->callback)
|
||||
download->callback(download, download->data);
|
||||
return 0;
|
||||
@ -885,7 +886,7 @@ load_uri(struct uri *uri, struct uri *referrer, struct download *download,
|
||||
if (cached) {
|
||||
if (download) {
|
||||
download->cached = cached;
|
||||
download->state = S_OK;
|
||||
download->state = connection_state(S_OK);
|
||||
/* XXX:
|
||||
* This doesn't work since sometimes |download->progress|
|
||||
* is undefined and contains random memory locations.
|
||||
@ -902,7 +903,7 @@ load_uri(struct uri *uri, struct uri *referrer, struct download *download,
|
||||
}
|
||||
|
||||
proxied_uri = get_proxied_uri(uri);
|
||||
proxy_uri = get_proxy_uri(uri, &connection_state);
|
||||
proxy_uri = get_proxy_uri(uri, &error_state);
|
||||
|
||||
if (!proxy_uri
|
||||
|| !proxied_uri
|
||||
@ -910,12 +911,13 @@ load_uri(struct uri *uri, struct uri *referrer, struct download *download,
|
||||
&& !proxy_uri->hostlen)) {
|
||||
|
||||
if (download) {
|
||||
if (connection_state == S_OK) {
|
||||
connection_state = proxy_uri && proxied_uri
|
||||
? S_BAD_URL : S_OUT_OF_MEM;
|
||||
if (is_in_state(error_state, S_OK)) {
|
||||
error_state = proxy_uri && proxied_uri
|
||||
? connection_state(S_BAD_URL)
|
||||
: connection_state(S_OUT_OF_MEM);
|
||||
}
|
||||
|
||||
download->state = connection_state;
|
||||
download->state = error_state;
|
||||
download->callback(download, download->data);
|
||||
}
|
||||
if (proxy_uri) done_uri(proxy_uri);
|
||||
@ -955,7 +957,7 @@ load_uri(struct uri *uri, struct uri *referrer, struct download *download,
|
||||
conn = init_connection(proxy_uri, proxied_uri, referrer, start, cache_mode, pri);
|
||||
if (!conn) {
|
||||
if (download) {
|
||||
download->state = S_OUT_OF_MEM;
|
||||
download->state = connection_state(S_OUT_OF_MEM);
|
||||
download->callback(download, download->data);
|
||||
}
|
||||
if (proxy_uri) done_uri(proxy_uri);
|
||||
@ -971,12 +973,12 @@ load_uri(struct uri *uri, struct uri *referrer, struct download *download,
|
||||
download->progress = conn->progress;
|
||||
download->conn = conn;
|
||||
download->cached = NULL;
|
||||
download->state = S_OK;
|
||||
download->state = connection_state(S_OK);
|
||||
add_to_list(conn->downloads, download);
|
||||
}
|
||||
|
||||
add_to_queue(conn);
|
||||
set_connection_state(conn, S_WAIT);
|
||||
set_connection_state(conn, connection_state(S_WAIT));
|
||||
|
||||
check_queue_bugs();
|
||||
|
||||
@ -1002,7 +1004,7 @@ cancel_download(struct download *download, int interrupt)
|
||||
|
||||
check_queue_bugs();
|
||||
|
||||
download->state = S_INTERRUPTED;
|
||||
download->state = connection_state(S_INTERRUPTED);
|
||||
del_from_list(download);
|
||||
|
||||
conn = download->conn;
|
||||
@ -1016,7 +1018,7 @@ cancel_download(struct download *download, int interrupt)
|
||||
conn->pri[PRI_CANCEL]++;
|
||||
|
||||
if (conn->detached || interrupt)
|
||||
abort_connection(conn, S_INTERRUPTED);
|
||||
abort_connection(conn, connection_state(S_INTERRUPTED));
|
||||
}
|
||||
|
||||
sort_queue();
|
||||
@ -1164,7 +1166,8 @@ void
|
||||
abort_all_connections(void)
|
||||
{
|
||||
while (!list_empty(connection_queue)) {
|
||||
abort_connection(connection_queue.next, S_INTERRUPTED);
|
||||
abort_connection(connection_queue.next,
|
||||
connection_state(S_INTERRUPTED));
|
||||
}
|
||||
|
||||
abort_all_keepalive_connections();
|
||||
@ -1177,7 +1180,7 @@ abort_background_connections(void)
|
||||
|
||||
foreachsafe (conn, next, connection_queue) {
|
||||
if (get_priority(conn) >= PRI_CANCEL)
|
||||
abort_connection(conn, S_INTERRUPTED);
|
||||
abort_connection(conn, connection_state(S_INTERRUPTED));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,8 +40,8 @@ struct connection {
|
||||
|
||||
unsigned int id;
|
||||
|
||||
enum connection_state state;
|
||||
enum connection_state prev_error;
|
||||
struct connection_state state;
|
||||
struct connection_state prev_error;
|
||||
|
||||
/* The communication socket with the other side. */
|
||||
struct socket *socket;
|
||||
@ -81,14 +81,14 @@ int get_keepalive_connections_count(void);
|
||||
int get_connections_connecting_count(void);
|
||||
int get_connections_transfering_count(void);
|
||||
|
||||
void set_connection_state(struct connection *, enum connection_state);
|
||||
void set_connection_state(struct connection *, struct connection_state);
|
||||
|
||||
int has_keepalive_connection(struct connection *);
|
||||
void add_keepalive_connection(struct connection *conn, long timeout_in_seconds,
|
||||
void (*done)(struct connection *));
|
||||
|
||||
void abort_connection(struct connection *, enum connection_state);
|
||||
void retry_connection(struct connection *, enum connection_state);
|
||||
void abort_connection(struct connection *, struct connection_state);
|
||||
void retry_connection(struct connection *, struct connection_state);
|
||||
|
||||
void cancel_download(struct download *download, int interrupt);
|
||||
void move_download(struct download *old, struct download *new,
|
||||
|
@ -167,13 +167,13 @@ close_socket(struct socket *socket)
|
||||
void
|
||||
dns_exception(struct socket *socket)
|
||||
{
|
||||
connect_socket(socket, S_EXCEPT);
|
||||
connect_socket(socket, connection_state(S_EXCEPT));
|
||||
}
|
||||
|
||||
static void
|
||||
exception(struct socket *socket)
|
||||
{
|
||||
socket->ops->retry(socket, S_EXCEPT);
|
||||
socket->ops->retry(socket, connection_state(S_EXCEPT));
|
||||
}
|
||||
|
||||
|
||||
@ -181,23 +181,23 @@ void
|
||||
timeout_socket(struct socket *socket)
|
||||
{
|
||||
if (!socket->connect_info) {
|
||||
socket->ops->retry(socket, S_TIMEOUT);
|
||||
socket->ops->retry(socket, connection_state(S_TIMEOUT));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Is the DNS resolving still in progress? */
|
||||
if (socket->connect_info->dnsquery) {
|
||||
socket->ops->done(socket, S_TIMEOUT);
|
||||
socket->ops->done(socket, connection_state(S_TIMEOUT));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Try the next address, */
|
||||
connect_socket(socket, S_TIMEOUT);
|
||||
connect_socket(socket, connection_state(S_TIMEOUT));
|
||||
|
||||
/* Reset the timeout if connect_socket() started a new attempt
|
||||
* to connect. */
|
||||
if (socket->connect_info)
|
||||
socket->ops->set_timeout(socket, 0);
|
||||
socket->ops->set_timeout(socket, connection_state(0));
|
||||
}
|
||||
|
||||
|
||||
@ -209,7 +209,7 @@ dns_found(struct socket *socket, struct sockaddr_storage *addr, int addrlen)
|
||||
int size;
|
||||
|
||||
if (!addr) {
|
||||
socket->ops->done(socket, S_NO_DNS);
|
||||
socket->ops->done(socket, connection_state(S_NO_DNS));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -219,7 +219,7 @@ dns_found(struct socket *socket, struct sockaddr_storage *addr, int addrlen)
|
||||
|
||||
connect_info->addr = mem_alloc(size);
|
||||
if (!connect_info->addr) {
|
||||
socket->ops->done(socket, S_OUT_OF_MEM);
|
||||
socket->ops->done(socket, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -233,7 +233,7 @@ dns_found(struct socket *socket, struct sockaddr_storage *addr, int addrlen)
|
||||
* problem if connect_socket() fails without doing any system calls
|
||||
* which is only the case when forcing the IP family. So it is better to
|
||||
* handle it in connect_socket(). */
|
||||
connect_socket(socket, S_CONN);
|
||||
connect_socket(socket, connection_state(S_CONN));
|
||||
}
|
||||
|
||||
void
|
||||
@ -244,17 +244,17 @@ make_connection(struct socket *socket, struct uri *uri,
|
||||
struct connect_info *connect_info;
|
||||
enum dns_result result;
|
||||
|
||||
socket->ops->set_timeout(socket, 0);
|
||||
socket->ops->set_timeout(socket, connection_state(0));
|
||||
|
||||
if (!host) {
|
||||
socket->ops->retry(socket, S_OUT_OF_MEM);
|
||||
socket->ops->retry(socket, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
connect_info = init_connection_info(uri, socket, connect_done);
|
||||
if (!connect_info) {
|
||||
mem_free(host);
|
||||
socket->ops->retry(socket, S_OUT_OF_MEM);
|
||||
socket->ops->retry(socket, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -278,7 +278,7 @@ make_connection(struct socket *socket, struct uri *uri,
|
||||
mem_free(host);
|
||||
|
||||
if (result == DNS_ASYNC)
|
||||
socket->ops->set_state(socket, S_DNS);
|
||||
socket->ops->set_state(socket, connection_state(S_DNS));
|
||||
}
|
||||
|
||||
|
||||
@ -316,7 +316,8 @@ get_pasv_socket(struct socket *ctrl_socket, struct sockaddr_storage *addr)
|
||||
if (getsockname(ctrl_socket->fd, pasv_addr, &len)) {
|
||||
sock_error:
|
||||
if (sock != -1) close(sock);
|
||||
ctrl_socket->ops->retry(ctrl_socket, -errno);
|
||||
ctrl_socket->ops->retry(ctrl_socket,
|
||||
connection_state_for_errno(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -454,7 +455,7 @@ complete_connect_socket(struct socket *socket, struct uri *uri,
|
||||
assert(uri && socket);
|
||||
connect_info = init_connection_info(uri, socket, done);
|
||||
if (!connect_info) {
|
||||
socket->ops->done(socket, S_OUT_OF_MEM);
|
||||
socket->ops->done(socket, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -482,6 +483,7 @@ static void
|
||||
connected(struct socket *socket)
|
||||
{
|
||||
int err = 0;
|
||||
struct connection_state state = connection_state(0);
|
||||
socklen_t len = sizeof(err);
|
||||
|
||||
assertm(socket->connect_info != NULL, "Lost connect_info!");
|
||||
@ -490,17 +492,21 @@ connected(struct socket *socket)
|
||||
if (getsockopt(socket->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len) == 0) {
|
||||
/* Why does EMX return so large values? */
|
||||
if (err >= 10000) err -= 10000;
|
||||
if (err != 0)
|
||||
state = connection_state_for_errno(err);
|
||||
else
|
||||
state = connection_state(0);
|
||||
} else {
|
||||
/* getsockopt() failed */
|
||||
if (errno > 0)
|
||||
err = errno;
|
||||
if (errno != 0)
|
||||
state = connection_state_for_errno(errno);
|
||||
else
|
||||
err = -(S_STATE);
|
||||
state = connection_state(S_STATE);
|
||||
}
|
||||
|
||||
if (err > 0) {
|
||||
if (!is_in_state(state, 0)) {
|
||||
/* There are maybe still some more candidates. */
|
||||
connect_socket(socket, -err);
|
||||
connect_socket(socket, state);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -508,7 +514,7 @@ connected(struct socket *socket)
|
||||
}
|
||||
|
||||
void
|
||||
connect_socket(struct socket *csocket, enum connection_state state)
|
||||
connect_socket(struct socket *csocket, struct connection_state state)
|
||||
{
|
||||
int sock = -1;
|
||||
struct connect_info *connect_info = csocket->connect_info;
|
||||
@ -640,7 +646,7 @@ connect_socket(struct socket *csocket, enum connection_state state)
|
||||
/* It will take some more time... */
|
||||
set_handlers(sock, NULL, (select_handler_T) connected,
|
||||
(select_handler_T) dns_exception, csocket);
|
||||
csocket->ops->set_state(csocket, S_CONN);
|
||||
csocket->ops->set_state(csocket, connection_state(S_CONN));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -658,7 +664,7 @@ connect_socket(struct socket *csocket, enum connection_state state)
|
||||
* what matters is the last one because we do not know the
|
||||
* previous one's errno, and the added complexity wouldn't
|
||||
* really be worth it. */
|
||||
csocket->ops->done(csocket, S_LOCAL_ONLY);
|
||||
csocket->ops->done(csocket, connection_state(S_LOCAL_ONLY));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -666,10 +672,10 @@ connect_socket(struct socket *csocket, enum connection_state state)
|
||||
* new. Else use the S_DNS _progress_ state to make sure that no
|
||||
* download callbacks will report any errors. */
|
||||
if (trno != connect_info->triedno && !silent_fail)
|
||||
state = -errno;
|
||||
state = connection_state_for_errno(errno);
|
||||
else if (trno == -1 && silent_fail)
|
||||
/* All failed. */
|
||||
state = S_NO_FORCED_DNS;
|
||||
state = connection_state(S_NO_FORCED_DNS);
|
||||
|
||||
csocket->ops->retry(csocket, state);
|
||||
}
|
||||
@ -704,14 +710,14 @@ write_select(struct socket *socket)
|
||||
|
||||
assertm(wb != NULL, "write socket has no buffer");
|
||||
if_assert_failed {
|
||||
socket->ops->done(socket, S_INTERNAL);
|
||||
socket->ops->done(socket, connection_state(S_INTERNAL));
|
||||
return;
|
||||
}
|
||||
|
||||
/* We are making some progress, therefore reset the timeout; ie. when
|
||||
* uploading large files the time needed for all the data to be sent can
|
||||
* easily exceed the timeout. */
|
||||
socket->ops->set_timeout(socket, 0);
|
||||
socket->ops->set_timeout(socket, connection_state(0));
|
||||
|
||||
#if 0
|
||||
printf("ws: %d\n",wb->length-wb->pos);
|
||||
@ -731,17 +737,17 @@ write_select(struct socket *socket)
|
||||
|
||||
switch (wr) {
|
||||
case SOCKET_CANT_WRITE:
|
||||
socket->ops->retry(socket, S_CANT_WRITE);
|
||||
socket->ops->retry(socket, connection_state(S_CANT_WRITE));
|
||||
break;
|
||||
|
||||
case SOCKET_SYSCALL_ERROR:
|
||||
socket->ops->retry(socket, -errno);
|
||||
socket->ops->retry(socket, connection_state_for_errno(errno));
|
||||
break;
|
||||
|
||||
case SOCKET_INTERNAL_ERROR:
|
||||
/* The global errno variable is used for passing
|
||||
* internal connection_state error value. */
|
||||
socket->ops->done(socket, -errno);
|
||||
socket->ops->done(socket, connection_state(errno));
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -777,7 +783,7 @@ write_select(struct socket *socket)
|
||||
|
||||
void
|
||||
write_to_socket(struct socket *socket, unsigned char *data, int len,
|
||||
enum connection_state state, socket_write_T write_done)
|
||||
struct connection_state state, socket_write_T write_done)
|
||||
{
|
||||
select_handler_T read_handler;
|
||||
struct write_buffer *wb;
|
||||
@ -787,11 +793,11 @@ write_to_socket(struct socket *socket, unsigned char *data, int len,
|
||||
assert(len > 0);
|
||||
if_assert_failed return;
|
||||
|
||||
socket->ops->set_timeout(socket, 0);
|
||||
socket->ops->set_timeout(socket, connection_state(0));
|
||||
|
||||
wb = mem_alloc(sizeof(*wb) + len);
|
||||
if (!wb) {
|
||||
socket->ops->done(socket, S_OUT_OF_MEM);
|
||||
socket->ops->done(socket, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -834,14 +840,14 @@ read_select(struct socket *socket)
|
||||
|
||||
assertm(rb != NULL, "read socket has no buffer");
|
||||
if_assert_failed {
|
||||
socket->ops->done(socket, S_INTERNAL);
|
||||
socket->ops->done(socket, connection_state(S_INTERNAL));
|
||||
return;
|
||||
}
|
||||
|
||||
/* We are making some progress, therefore reset the timeout; we do this
|
||||
* for read_select() to avoid that the periodic calls to user handlers
|
||||
* has to do it. */
|
||||
socket->ops->set_timeout(socket, 0);
|
||||
socket->ops->set_timeout(socket, connection_state(0));
|
||||
|
||||
if (!socket->duplex)
|
||||
clear_handlers(socket->fd);
|
||||
@ -851,7 +857,7 @@ read_select(struct socket *socket)
|
||||
|
||||
rb = mem_realloc(rb, size);
|
||||
if (!rb) {
|
||||
socket->ops->done(socket, S_OUT_OF_MEM);
|
||||
socket->ops->done(socket, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
rb->freespace = size - sizeof(*rb) - rb->length;
|
||||
@ -871,7 +877,7 @@ read_select(struct socket *socket)
|
||||
switch (rd) {
|
||||
#ifdef CONFIG_SSL
|
||||
case SOCKET_SSL_WANT_READ:
|
||||
read_from_socket(socket, rb, S_TRANS, rb->done);
|
||||
read_from_socket(socket, rb, connection_state(S_TRANS), rb->done);
|
||||
break;
|
||||
#endif
|
||||
case SOCKET_CANT_READ:
|
||||
@ -881,15 +887,17 @@ read_select(struct socket *socket)
|
||||
break;
|
||||
}
|
||||
|
||||
errno = -S_CANT_READ;
|
||||
/* Fall-through */
|
||||
socket->ops->retry(socket, connection_state(S_CANT_READ));
|
||||
break;
|
||||
|
||||
case SOCKET_SYSCALL_ERROR:
|
||||
socket->ops->retry(socket, -errno);
|
||||
socket->ops->retry(socket, connection_state_for_errno(errno));
|
||||
break;
|
||||
|
||||
case SOCKET_INTERNAL_ERROR:
|
||||
socket->ops->done(socket, -errno);
|
||||
/* The global errno variable is used for passing
|
||||
* internal connection_state error value. */
|
||||
socket->ops->done(socket, connection_state(errno));
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -910,7 +918,7 @@ alloc_read_buffer(struct socket *socket)
|
||||
|
||||
rb = mem_calloc(1, RD_SIZE(rb, 0));
|
||||
if (!rb) {
|
||||
socket->ops->done(socket, S_OUT_OF_MEM);
|
||||
socket->ops->done(socket, connection_state(S_OUT_OF_MEM));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -925,13 +933,13 @@ alloc_read_buffer(struct socket *socket)
|
||||
|
||||
void
|
||||
read_from_socket(struct socket *socket, struct read_buffer *buffer,
|
||||
enum connection_state state, socket_read_T done)
|
||||
struct connection_state state, socket_read_T done)
|
||||
{
|
||||
select_handler_T write_handler;
|
||||
|
||||
buffer->done = done;
|
||||
|
||||
socket->ops->set_timeout(socket, 0);
|
||||
socket->ops->set_timeout(socket, connection_state(0));
|
||||
socket->ops->set_state(socket, state);
|
||||
|
||||
if (socket->read_buffer && buffer != socket->read_buffer)
|
||||
@ -953,12 +961,13 @@ read_response_from_socket(struct socket *socket)
|
||||
{
|
||||
struct read_buffer *rb = alloc_read_buffer(socket);
|
||||
|
||||
if (rb) read_from_socket(socket, rb, S_SENT, socket->read_done);
|
||||
if (rb) read_from_socket(socket, rb, connection_state(S_SENT),
|
||||
socket->read_done);
|
||||
}
|
||||
|
||||
void
|
||||
request_from_socket(struct socket *socket, unsigned char *data, int datalen,
|
||||
enum connection_state state, enum socket_state sock_state,
|
||||
struct connection_state state, enum socket_state sock_state,
|
||||
socket_read_T read_done)
|
||||
{
|
||||
socket->read_done = read_done;
|
||||
|
@ -16,8 +16,8 @@ struct uri;
|
||||
|
||||
/* Use internally for error return values. */
|
||||
enum socket_error {
|
||||
SOCKET_SYSCALL_ERROR = -1, /* Retry with -errno state. */
|
||||
SOCKET_INTERNAL_ERROR = -2, /* Stop with -errno state. */
|
||||
SOCKET_SYSCALL_ERROR = -1, /* Retry with connection_state_for_errno(errno). */
|
||||
SOCKET_INTERNAL_ERROR = -2, /* Stop with connection_state(errno). */
|
||||
SOCKET_SSL_WANT_READ = -3, /* Try to read some more. */
|
||||
SOCKET_CANT_READ = -4, /* Retry with S_CANT_READ state. */
|
||||
SOCKET_CANT_WRITE = -5, /* Retry with S_CANT_WRITE state. */
|
||||
@ -39,7 +39,7 @@ enum socket_state {
|
||||
typedef void (*socket_read_T)(struct socket *, struct read_buffer *);
|
||||
typedef void (*socket_write_T)(struct socket *);
|
||||
typedef void (*socket_connect_T)(struct socket *);
|
||||
typedef void (*socket_operation_T)(struct socket *, enum connection_state state);
|
||||
typedef void (*socket_operation_T)(struct socket *, struct connection_state);
|
||||
|
||||
struct socket_operations {
|
||||
/* Report change in the state of the socket. */
|
||||
@ -140,7 +140,7 @@ int get_pasv_socket(struct socket *ctrl_socket, struct sockaddr_storage *addr);
|
||||
/* Try to connect to the next available address or force the connection to retry
|
||||
* if all has already been tried. Updates the connection state to
|
||||
* @connection_state. */
|
||||
void connect_socket(struct socket *socket, enum connection_state state);
|
||||
void connect_socket(struct socket *socket, struct connection_state state);
|
||||
|
||||
/* Used by the SSL layer when negotiating. */
|
||||
void dns_exception(struct socket *socket);
|
||||
@ -151,17 +151,17 @@ void dns_exception(struct socket *socket);
|
||||
/* Reads data from @socket into @buffer. Calls @done each time new data is
|
||||
* ready. */
|
||||
void read_from_socket(struct socket *socket, struct read_buffer *buffer,
|
||||
enum connection_state state, socket_read_T done);
|
||||
struct connection_state state, socket_read_T done);
|
||||
|
||||
/* Writes @datalen bytes from @data buffer to the passed @socket. When all data
|
||||
* is written the @done callback will be called. */
|
||||
void write_to_socket(struct socket *socket,
|
||||
unsigned char *data, int datalen,
|
||||
enum connection_state state, socket_write_T write_done);
|
||||
struct connection_state state, socket_write_T write_done);
|
||||
|
||||
/* Send request and get response. */
|
||||
void request_from_socket(struct socket *socket, unsigned char *data, int datalen,
|
||||
enum connection_state state, enum socket_state sock_state,
|
||||
struct connection_state state, enum socket_state sock_state,
|
||||
socket_read_T read_done);
|
||||
|
||||
/* Initialize a read buffer. */
|
||||
|
@ -93,7 +93,7 @@ ssl_want_read(struct socket *socket)
|
||||
#ifdef CONFIG_GNUTLS
|
||||
if (get_opt_bool("connection.ssl.cert_verify")
|
||||
&& gnutls_certificate_verify_peers(*((ssl_t *) socket->ssl))) {
|
||||
socket->ops->retry(socket, S_SSL_ERROR);
|
||||
socket->ops->retry(socket, connection_state(S_SSL_ERROR));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@ -108,7 +108,7 @@ ssl_want_read(struct socket *socket)
|
||||
|
||||
default:
|
||||
socket->no_tls = !socket->no_tls;
|
||||
socket->ops->retry(socket, S_SSL_ERROR);
|
||||
socket->ops->retry(socket, connection_state(S_SSL_ERROR));
|
||||
}
|
||||
}
|
||||
|
||||
@ -119,7 +119,7 @@ ssl_connect(struct socket *socket)
|
||||
int ret;
|
||||
|
||||
if (init_ssl_connection(socket) == S_SSL_ERROR) {
|
||||
socket->ops->done(socket, S_SSL_ERROR);
|
||||
socket->ops->done(socket, connection_state(S_SSL_ERROR));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -172,7 +172,7 @@ ssl_connect(struct socket *socket)
|
||||
switch (ret) {
|
||||
case SSL_ERROR_WANT_READ:
|
||||
case SSL_ERROR_WANT_READ2:
|
||||
socket->ops->set_state(socket, S_SSL_NEG);
|
||||
socket->ops->set_state(socket, connection_state(S_SSL_NEG));
|
||||
set_handlers(socket->fd, (select_handler_T) ssl_want_read,
|
||||
NULL, (select_handler_T) dns_exception, socket);
|
||||
return -1;
|
||||
@ -192,14 +192,14 @@ ssl_connect(struct socket *socket)
|
||||
socket->no_tls = !socket->no_tls;
|
||||
}
|
||||
|
||||
connect_socket(socket, S_SSL_ERROR);
|
||||
connect_socket(socket, connection_state(S_SSL_ERROR));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return -1 on error, bytes written on success. */
|
||||
/* Return enum socket_error on error, bytes written on success. */
|
||||
ssize_t
|
||||
ssl_write(struct socket *socket, unsigned char *data, int len)
|
||||
{
|
||||
@ -221,15 +221,14 @@ ssl_write(struct socket *socket, unsigned char *data, int len)
|
||||
if (err == SSL_ERROR_SYSCALL)
|
||||
return SOCKET_SYSCALL_ERROR;
|
||||
|
||||
errno = -S_SSL_ERROR;
|
||||
|
||||
errno = S_SSL_ERROR;
|
||||
return SOCKET_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
return wr;
|
||||
}
|
||||
|
||||
/* Return -1 on error, rd or success. */
|
||||
/* Return enum socket_error on error, bytes read on success. */
|
||||
ssize_t
|
||||
ssl_read(struct socket *socket, unsigned char *data, int len)
|
||||
{
|
||||
@ -257,8 +256,7 @@ ssl_read(struct socket *socket, unsigned char *data, int len)
|
||||
if (err == SSL_ERROR_SYSCALL2)
|
||||
return SOCKET_SYSCALL_ERROR;
|
||||
|
||||
errno = -S_SSL_ERROR;
|
||||
|
||||
errno = S_SSL_ERROR;
|
||||
return SOCKET_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
|
@ -142,7 +142,7 @@ static INIT_LIST_OF(struct strerror_val, strerror_buf);
|
||||
* It never returns NULL (if one changes that, be warn that
|
||||
* callers may not test for this condition) --Zas */
|
||||
unsigned char *
|
||||
get_state_message(enum connection_state state, struct terminal *term)
|
||||
get_state_message(struct connection_state state, struct terminal *term)
|
||||
{
|
||||
unsigned char *e;
|
||||
struct strerror_val *s;
|
||||
@ -153,13 +153,13 @@ get_state_message(enum connection_state state, struct terminal *term)
|
||||
int i;
|
||||
|
||||
for (i = 0; msg_dsc[i].msg; i++)
|
||||
if (msg_dsc[i].n == state)
|
||||
if (msg_dsc[i].n == state.basic)
|
||||
return _(msg_dsc[i].msg, term);
|
||||
|
||||
return unknown_error;
|
||||
}
|
||||
|
||||
e = (unsigned char *) strerror(-state);
|
||||
e = (unsigned char *) strerror(state.syserr);
|
||||
if (!e || !*e) return unknown_error;
|
||||
|
||||
len = strlen(e);
|
||||
|
@ -1,6 +1,8 @@
|
||||
#ifndef EL__NETWORK_STATE_H
|
||||
#define EL__NETWORK_STATE_H
|
||||
|
||||
#include "util/error.h" /* assert() */
|
||||
|
||||
struct terminal;
|
||||
|
||||
enum connection_priority {
|
||||
@ -15,23 +17,18 @@ enum connection_priority {
|
||||
PRIORITIES,
|
||||
};
|
||||
|
||||
/* Numbers < 0 and > -100000 are reserved for system errors reported via
|
||||
* errno/strerror(), see session.c and connection.c for further information. */
|
||||
/* WARNING: an errno value <= -100000 may cause some bad things... */
|
||||
/* NOTE: Winsock errors are in range 10000..11004. Hence our abs. values are
|
||||
* above this. */
|
||||
|
||||
#define is_system_error(state) (S_OK < (state) && (state) < S_WAIT)
|
||||
#define is_in_result_state(state) ((state) < 0)
|
||||
#define is_in_progress_state(state) ((state) >= 0)
|
||||
#define is_in_connecting_state(state) (S_WAIT < (state) && (state) < S_TRANS)
|
||||
#define is_in_transfering_state(state) ((state) >= S_TRANS)
|
||||
#define is_in_queued_state(state) (is_in_connecting_state(state) || (state) == S_WAIT)
|
||||
#define is_system_error(state) ((state).basic == S_ERRNO)
|
||||
#define is_in_state(state,basic_) ((state).basic == (basic_))
|
||||
#define is_in_result_state(state) ((state).basic < 0)
|
||||
#define is_in_progress_state(state) ((state).basic >= 0)
|
||||
#define is_in_connecting_state(state) (S_WAIT < (state).basic && (state).basic < S_TRANS)
|
||||
#define is_in_transfering_state(state) ((state).basic >= S_TRANS)
|
||||
#define is_in_queued_state(state) (is_in_connecting_state(state) || (state).basic == S_WAIT)
|
||||
|
||||
/* FIXME: Namespace clash with Windows headers. */
|
||||
#undef S_OK
|
||||
|
||||
enum connection_state {
|
||||
enum connection_basic_state {
|
||||
/* States >= 0 are used for connections still in progress. */
|
||||
S_WAIT = 0,
|
||||
S_DNS,
|
||||
@ -49,6 +46,7 @@ enum connection_state {
|
||||
|
||||
/* State < 0 are used for the final result of a connection
|
||||
* (it's finished already and it ended up like this) */
|
||||
S_ERRNO = -1,
|
||||
S_OK = -100000,
|
||||
S_INTERRUPTED = -100001,
|
||||
S_EXCEPT = -100002,
|
||||
@ -107,7 +105,44 @@ enum connection_state {
|
||||
S_BITTORRENT_BAD_URL = -100803,
|
||||
};
|
||||
|
||||
unsigned char *get_state_message(enum connection_state state, struct terminal *term);
|
||||
/** Either an ELinks internal status code or an error code from the
|
||||
* system. Use connection_state() or connection_state_for_errno()
|
||||
* to construct objects of this type. */
|
||||
struct connection_state {
|
||||
/** An ELinks internal status code, or ::S_ERRNO if this
|
||||
* structure holds a system error instead. */
|
||||
enum connection_basic_state basic;
|
||||
|
||||
/** When #state is ::S_ERRNO, syserr is the saved value of
|
||||
* errno. Otherwise, syserr should be 0. */
|
||||
int syserr;
|
||||
};
|
||||
|
||||
unsigned char *get_state_message(struct connection_state state, struct terminal *term);
|
||||
void done_state_message(void);
|
||||
|
||||
static inline struct connection_state
|
||||
connection_state(enum connection_basic_state basic)
|
||||
{
|
||||
struct connection_state state = {0};
|
||||
|
||||
assert(basic != S_ERRNO);
|
||||
if_assert_failed basic = S_INTERNAL;
|
||||
|
||||
state.basic = basic;
|
||||
return state;
|
||||
}
|
||||
|
||||
static inline struct connection_state
|
||||
connection_state_for_errno(int syserr)
|
||||
{
|
||||
struct connection_state state = {0};
|
||||
|
||||
/* read_encoded_file() can pass syserr==0 here, so don't
|
||||
* assert otherwise. */
|
||||
state.basic = S_ERRNO;
|
||||
state.syserr = syserr;
|
||||
return state;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -119,5 +119,5 @@ about_protocol_handler(struct connection *conn)
|
||||
}
|
||||
|
||||
conn->cached = cached;
|
||||
abort_connection(conn, S_OK);
|
||||
abort_connection(conn, connection_state(S_OK));
|
||||
}
|
||||
|
@ -294,7 +294,7 @@ add_bittorrent_selection(struct uri *uri, int *selection, size_t size)
|
||||
static INIT_LIST_OF(struct bittorrent_message, bittorrent_messages);
|
||||
|
||||
void
|
||||
add_bittorrent_message(struct uri *uri, enum connection_state state,
|
||||
add_bittorrent_message(struct uri *uri, struct connection_state state,
|
||||
struct string *string)
|
||||
{
|
||||
struct bittorrent_message *message;
|
||||
|
@ -16,7 +16,7 @@ uint32_t get_bittorrent_peerwire_max_request_length(void);
|
||||
int *get_bittorrent_selection(struct uri *uri, size_t size);
|
||||
void add_bittorrent_selection(struct uri *uri, int *selection, size_t size);
|
||||
|
||||
void add_bittorrent_message(struct uri *uri, enum connection_state state,
|
||||
void add_bittorrent_message(struct uri *uri, struct connection_state state,
|
||||
struct string *);
|
||||
|
||||
#endif
|
||||
|
@ -335,13 +335,14 @@ bittorrent_fetch_callback(struct download *download, void *data)
|
||||
struct cache_entry *cached = download->cached;
|
||||
|
||||
/* If the callback was removed we should shutdown ASAP. */
|
||||
if (!fetcher->callback || download->state == S_INTERRUPTED) {
|
||||
if (download->state == S_INTERRUPTED)
|
||||
if (!fetcher->callback || is_in_state(download->state, S_INTERRUPTED)) {
|
||||
if (is_in_state(download->state, S_INTERRUPTED))
|
||||
mem_free(fetcher);
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_in_result_state(download->state) && download->state != S_OK) {
|
||||
if (is_in_result_state(download->state)
|
||||
&& !is_in_state(download->state, S_OK)) {
|
||||
fetcher->callback(fetcher->data, download->state, NULL);
|
||||
if (fetcher->ref)
|
||||
*fetcher->ref = NULL;
|
||||
@ -355,7 +356,7 @@ bittorrent_fetch_callback(struct download *download, void *data)
|
||||
if (cached->redirect && fetcher->redirects++ < MAX_REDIRECTS) {
|
||||
cancel_download(download, 0);
|
||||
|
||||
download->state = S_WAIT_REDIR;
|
||||
download->state = connection_state(S_WAIT_REDIR);
|
||||
|
||||
load_uri(cached->redirect, cached->uri, download,
|
||||
PRI_DOWNLOAD, CACHE_MODE_NORMAL,
|
||||
@ -367,13 +368,13 @@ bittorrent_fetch_callback(struct download *download, void *data)
|
||||
if (is_in_progress_state(download->state))
|
||||
return;
|
||||
|
||||
assert(download->state == S_OK);
|
||||
assert(is_in_state(download->state, S_OK));
|
||||
|
||||
/* If the entry is chunked defragment it and grab the single, remaining
|
||||
* fragment. */
|
||||
fragment = get_cache_fragment(cached);
|
||||
if (!fragment) {
|
||||
fetcher->callback(fetcher->data, S_OUT_OF_MEM, NULL);
|
||||
fetcher->callback(fetcher->data, connection_state(S_OUT_OF_MEM), NULL);
|
||||
if (fetcher->ref)
|
||||
*fetcher->ref = NULL;
|
||||
mem_free(fetcher);
|
||||
@ -383,7 +384,7 @@ bittorrent_fetch_callback(struct download *download, void *data)
|
||||
response.source = fragment->data;
|
||||
response.length = fragment->length;
|
||||
|
||||
fetcher->callback(fetcher->data, S_OK, &response);
|
||||
fetcher->callback(fetcher->data, connection_state(S_OK), &response);
|
||||
|
||||
if (fetcher->delete)
|
||||
delete_cache_entry(cached);
|
||||
@ -401,7 +402,7 @@ init_bittorrent_fetch(struct bittorrent_fetcher **fetcher_ref,
|
||||
|
||||
fetcher = mem_calloc(1, sizeof(*fetcher));
|
||||
if (!fetcher) {
|
||||
callback(data, S_OUT_OF_MEM, NULL);
|
||||
callback(data, connection_state(S_OUT_OF_MEM), NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ struct bittorrent_message {
|
||||
LIST_HEAD(struct bittorrent_message);
|
||||
|
||||
struct uri *uri;
|
||||
enum connection_state state;
|
||||
struct connection_state state;
|
||||
unsigned char string[1];
|
||||
};
|
||||
|
||||
@ -404,7 +404,7 @@ del_bittorrent_peer_request(struct bittorrent_peer_status *status,
|
||||
/* URI fetching: */
|
||||
/* ************************************************************************** */
|
||||
|
||||
typedef void (*bittorrent_fetch_callback_T)(void *, enum connection_state, struct string *);
|
||||
typedef void (*bittorrent_fetch_callback_T)(void *, struct connection_state, struct string *);
|
||||
|
||||
struct bittorrent_fetcher *
|
||||
init_bittorrent_fetch(struct bittorrent_fetcher **fetcher_ref,
|
||||
|
@ -301,22 +301,22 @@ init_bittorrent_connection(struct connection *conn)
|
||||
void
|
||||
bittorrent_resume_callback(struct bittorrent_connection *bittorrent)
|
||||
{
|
||||
enum connection_state state;
|
||||
struct connection_state state;
|
||||
|
||||
/* Failing to create the listening socket is fatal. */
|
||||
state = init_bittorrent_listening_socket(bittorrent->conn);
|
||||
if (state != S_OK) {
|
||||
if (!is_in_state(state, S_OK)) {
|
||||
retry_connection(bittorrent->conn, state);
|
||||
return;
|
||||
}
|
||||
|
||||
set_connection_state(bittorrent->conn, S_CONN_TRACKER);
|
||||
set_connection_state(bittorrent->conn, connection_state(S_CONN_TRACKER));
|
||||
send_bittorrent_tracker_request(bittorrent->conn);
|
||||
}
|
||||
|
||||
/* Metainfo file download callback */
|
||||
static void
|
||||
bittorrent_metainfo_callback(void *data, enum connection_state state,
|
||||
bittorrent_metainfo_callback(void *data, struct connection_state state,
|
||||
struct string *response)
|
||||
{
|
||||
struct connection *conn = data;
|
||||
@ -324,7 +324,7 @@ bittorrent_metainfo_callback(void *data, enum connection_state state,
|
||||
|
||||
bittorrent->fetch = NULL;
|
||||
|
||||
if (state != S_OK) {
|
||||
if (!is_in_state(state, S_OK)) {
|
||||
abort_connection(conn, state);
|
||||
return;
|
||||
}
|
||||
@ -354,21 +354,22 @@ bittorrent_metainfo_callback(void *data, enum connection_state state,
|
||||
return;
|
||||
|
||||
case BITTORRENT_STATE_CACHE_RESUME:
|
||||
set_connection_state(bittorrent->conn, S_RESUME);
|
||||
set_connection_state(bittorrent->conn,
|
||||
connection_state(S_RESUME));
|
||||
return;
|
||||
|
||||
case BITTORRENT_STATE_OUT_OF_MEM:
|
||||
state = S_OUT_OF_MEM;
|
||||
state = connection_state(S_OUT_OF_MEM);
|
||||
break;
|
||||
|
||||
default:
|
||||
state = S_BITTORRENT_ERROR;
|
||||
state = connection_state(S_BITTORRENT_ERROR);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case BITTORRENT_STATE_OUT_OF_MEM:
|
||||
state = S_OUT_OF_MEM;
|
||||
state = connection_state(S_OUT_OF_MEM);
|
||||
break;
|
||||
|
||||
case BITTORRENT_STATE_ERROR:
|
||||
@ -378,7 +379,7 @@ bittorrent_metainfo_callback(void *data, enum connection_state state,
|
||||
* looking at the protocol header, however, direct usage of the
|
||||
* internal bittorrent: is at your own risk ... at least for
|
||||
* now. --jonas */
|
||||
state = S_BITTORRENT_METAINFO;
|
||||
state = connection_state(S_BITTORRENT_METAINFO);
|
||||
}
|
||||
|
||||
abort_connection(conn, state);
|
||||
@ -393,7 +394,7 @@ bittorrent_protocol_handler(struct connection *conn)
|
||||
|
||||
bittorrent = init_bittorrent_connection(conn);
|
||||
if (!bittorrent) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -401,11 +402,11 @@ bittorrent_protocol_handler(struct connection *conn)
|
||||
uri = get_uri(conn->uri->data, 0);
|
||||
|
||||
if (!uri) {
|
||||
abort_connection(conn, S_BITTORRENT_BAD_URL);
|
||||
abort_connection(conn, connection_state(S_BITTORRENT_BAD_URL));
|
||||
return;
|
||||
}
|
||||
|
||||
set_connection_state(conn, S_CONN);
|
||||
set_connection_state(conn, connection_state(S_CONN));
|
||||
set_connection_timeout(conn);
|
||||
conn->from = 0;
|
||||
|
||||
|
@ -531,7 +531,7 @@ draw_bittorrent_piece_progress(struct download *download, struct terminal *term,
|
||||
}
|
||||
}
|
||||
|
||||
if (download->state == S_RESUME) {
|
||||
if (is_in_state(download->state, S_RESUME)) {
|
||||
static unsigned char s[] = "????"; /* Reduce or enlarge at will. */
|
||||
unsigned int slen = 0;
|
||||
int max = int_min(sizeof(s), width) - 1;
|
||||
@ -587,9 +587,10 @@ bittorrent_message_dialog(struct session *ses, void *data)
|
||||
add_to_string(&string, ":\n\n");
|
||||
}
|
||||
|
||||
if (message->state != S_OK) {
|
||||
if (!is_in_state(message->state, S_OK)) {
|
||||
add_format_to_string(&string, "%s: %s",
|
||||
get_state_message(S_BITTORRENT_TRACKER, ses->tab->term),
|
||||
get_state_message(connection_state(S_BITTORRENT_TRACKER),
|
||||
ses->tab->term),
|
||||
get_state_message(message->state, ses->tab->term));
|
||||
} else {
|
||||
add_to_string(&string, message->string);
|
||||
@ -686,7 +687,7 @@ tp_show_header(struct dialog_data *dlg_data, struct widget_data *widget_data)
|
||||
|
||||
/* Build a dialog querying the user on how to handle a .torrent file. */
|
||||
static void
|
||||
bittorrent_query_callback(void *data, enum connection_state state,
|
||||
bittorrent_query_callback(void *data, struct connection_state state,
|
||||
struct string *response)
|
||||
{
|
||||
/* [gettext_accelerator_context(.bittorrent_query_callback)] */
|
||||
@ -705,7 +706,7 @@ bittorrent_query_callback(void *data, enum connection_state state,
|
||||
struct string msg;
|
||||
int files;
|
||||
|
||||
if (state != S_OK)
|
||||
if (!is_in_state(state, S_OK))
|
||||
return;
|
||||
|
||||
/* This should never happen, since setup_download_handler() should make
|
||||
@ -739,7 +740,8 @@ bittorrent_query_callback(void *data, enum connection_state state,
|
||||
done_string(&filename);
|
||||
|
||||
if (parse_bittorrent_metafile(&meta, response) != BITTORRENT_STATE_OK) {
|
||||
print_error_dialog(type_query->ses, S_BITTORRENT_METAINFO,
|
||||
print_error_dialog(type_query->ses,
|
||||
connection_state(S_BITTORRENT_METAINFO),
|
||||
type_query->uri, PRI_CANCEL);
|
||||
tp_cancel(type_query);
|
||||
done_string(&msg);
|
||||
|
@ -67,7 +67,7 @@ find_bittorrent_connection(bittorrent_id_T info_hash)
|
||||
|
||||
static void
|
||||
check_bittorrent_peer_blacklisting(struct bittorrent_peer_connection *peer,
|
||||
enum connection_state state)
|
||||
struct connection_state state)
|
||||
{
|
||||
enum bittorrent_blacklist_flags flags = BITTORRENT_BLACKLIST_NONE;
|
||||
|
||||
@ -75,12 +75,15 @@ check_bittorrent_peer_blacklisting(struct bittorrent_peer_connection *peer,
|
||||
|| !get_opt_bool("protocol.http.bugs.allow_blacklist"))
|
||||
return;
|
||||
|
||||
switch (state) {
|
||||
case -ECONNREFUSED:
|
||||
case -ENETUNREACH:
|
||||
if (is_system_error(state)) {
|
||||
switch (state.syserr) {
|
||||
case ECONNREFUSED:
|
||||
case ENETUNREACH:
|
||||
flags |= BITTORRENT_BLACKLIST_PEER_POOL;
|
||||
break;
|
||||
|
||||
}
|
||||
} else {
|
||||
switch (state.basic) {
|
||||
case S_CANT_WRITE:
|
||||
case S_CANT_READ:
|
||||
if (!peer->local.handshake
|
||||
@ -91,6 +94,7 @@ check_bittorrent_peer_blacklisting(struct bittorrent_peer_connection *peer,
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags != BITTORRENT_BLACKLIST_NONE) {
|
||||
add_bittorrent_blacklist_flags(peer->id, flags);
|
||||
@ -137,30 +141,30 @@ set_bittorrent_peer_connection_timeout(struct bittorrent_peer_connection *peer)
|
||||
* S_DMS (while looking up the host) then moves to S_CONN (while connecting),
|
||||
* and should hopefully become S_TRANS (while transfering). Note, state can hold
|
||||
* both internally defined connection states as described above and errno
|
||||
* values, such as ECONNREFUSED. The errno values are passed negative so in the
|
||||
* previous example the errno would be passed as -ECONNREFUSED. */
|
||||
* values, such as ECONNREFUSED. */
|
||||
static void
|
||||
set_bittorrent_socket_state(struct socket *socket, enum connection_state state)
|
||||
set_bittorrent_socket_state(struct socket *socket, struct connection_state state)
|
||||
{
|
||||
struct bittorrent_peer_connection *peer = socket->conn;
|
||||
|
||||
if (state == S_TRANS && peer->bittorrent)
|
||||
set_connection_state(peer->bittorrent->conn, S_TRANS);
|
||||
if (is_in_state(state, S_TRANS) && peer->bittorrent)
|
||||
set_connection_state(peer->bittorrent->conn,
|
||||
connection_state(S_TRANS));
|
||||
}
|
||||
|
||||
/* Called when progress is made such as when the select() loop detects and
|
||||
* schedules reads and writes. The state variable must be ignored. */
|
||||
static void
|
||||
set_bittorrent_socket_timeout(struct socket *socket, enum connection_state state)
|
||||
set_bittorrent_socket_timeout(struct socket *socket, struct connection_state state)
|
||||
{
|
||||
assert(state == 0);
|
||||
assert(is_in_state(state, 0));
|
||||
set_bittorrent_peer_connection_timeout(socket->conn);
|
||||
}
|
||||
|
||||
/* Called when a non-fatal error condition has appeared, i.e. the condition is
|
||||
* caused by some internal or local system error or simply a timeout. */
|
||||
static void
|
||||
retry_bittorrent_socket(struct socket *socket, enum connection_state state)
|
||||
retry_bittorrent_socket(struct socket *socket, struct connection_state state)
|
||||
{
|
||||
struct bittorrent_peer_connection *peer = socket->conn;
|
||||
|
||||
@ -177,7 +181,7 @@ retry_bittorrent_socket(struct socket *socket, enum connection_state state)
|
||||
/* Called when a fatal and unrecoverable error condition has appeared, such as a
|
||||
* DNS query failed. */
|
||||
static void
|
||||
done_bittorrent_socket(struct socket *socket, enum connection_state state)
|
||||
done_bittorrent_socket(struct socket *socket, struct connection_state state)
|
||||
{
|
||||
struct bittorrent_peer_connection *peer = socket->conn;
|
||||
|
||||
@ -344,7 +348,7 @@ accept_bittorrent_peer_connection(void *____)
|
||||
buffer = alloc_read_buffer(peer->socket);
|
||||
if (!buffer) return;
|
||||
|
||||
read_from_socket(peer->socket, buffer, S_TRANS,
|
||||
read_from_socket(peer->socket, buffer, connection_state(S_TRANS),
|
||||
read_bittorrent_peer_handshake);
|
||||
|
||||
add_to_list(bittorrent_peer_connections, peer);
|
||||
@ -352,7 +356,7 @@ accept_bittorrent_peer_connection(void *____)
|
||||
|
||||
/* Based on network/socket.c:get_pasv_socket() but modified to try and bind to a
|
||||
* port range instead of any port. */
|
||||
enum connection_state
|
||||
struct connection_state
|
||||
init_bittorrent_listening_socket(struct connection *conn)
|
||||
{
|
||||
struct bittorrent_connection *bittorrent = conn->info;
|
||||
@ -366,7 +370,7 @@ init_bittorrent_listening_socket(struct connection *conn)
|
||||
|
||||
/* Has the socket already been initialized? */
|
||||
if (!list_is_singleton(bittorrent_connections))
|
||||
return S_OK;
|
||||
return connection_state(S_OK);
|
||||
|
||||
/* We could have bailed out from an earlier attempt. */
|
||||
if (bittorrent_socket != -1)
|
||||
@ -374,12 +378,12 @@ init_bittorrent_listening_socket(struct connection *conn)
|
||||
|
||||
bittorrent_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (bittorrent_socket < 0)
|
||||
return -errno;
|
||||
return connection_state_for_errno(errno);
|
||||
|
||||
/* Set it non-blocking */
|
||||
|
||||
if (set_nonblocking_fd(bittorrent_socket) < 0)
|
||||
return -errno;
|
||||
return connection_state_for_errno(errno);
|
||||
|
||||
/* Bind it to some port */
|
||||
|
||||
@ -392,11 +396,11 @@ init_bittorrent_listening_socket(struct connection *conn)
|
||||
/* Repeatedly try the configured port range. */
|
||||
while (bind(bittorrent_socket, (struct sockaddr *) &addr, sizeof(addr))) {
|
||||
if (errno != EADDRINUSE)
|
||||
return -errno;
|
||||
return connection_state_for_errno(errno);
|
||||
|
||||
/* If all ports was in use fail with EADDRINUSE. */
|
||||
if (++port > max_port)
|
||||
return -errno;
|
||||
return connection_state_for_errno(errno);
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_port = htons(port);
|
||||
@ -407,20 +411,20 @@ init_bittorrent_listening_socket(struct connection *conn)
|
||||
memset(&addr2, 0, sizeof(addr2));
|
||||
len = sizeof(addr2);
|
||||
if (getsockname(bittorrent_socket, (struct sockaddr *) &addr2, &len))
|
||||
return -errno;
|
||||
return connection_state_for_errno(errno);
|
||||
|
||||
bittorrent->port = ntohs(addr2.sin_port);
|
||||
|
||||
/* Go listen */
|
||||
|
||||
if (listen(bittorrent_socket, LISTEN_BACKLOG))
|
||||
return -errno;
|
||||
return connection_state_for_errno(errno);
|
||||
|
||||
set_ip_tos_throughput(bittorrent_socket);
|
||||
set_handlers(bittorrent_socket, accept_bittorrent_peer_connection,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
return S_OK;
|
||||
return connection_state(S_OK);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -8,7 +8,7 @@
|
||||
struct connection;
|
||||
|
||||
/* Sets up and tears down the peer listening socket. */
|
||||
enum connection_state init_bittorrent_listening_socket(struct connection *conn);
|
||||
struct connection_state init_bittorrent_listening_socket(struct connection *conn);
|
||||
void done_bittorrent_listening_socket(struct connection *conn);
|
||||
|
||||
void done_bittorrent_peer_connection(struct bittorrent_peer_connection *peer);
|
||||
|
@ -349,7 +349,8 @@ do_send_bittorrent_peer_message(struct bittorrent_peer_connection *peer,
|
||||
}
|
||||
|
||||
write_to_socket(peer->socket, string.source, string.length,
|
||||
S_TRANS, sent_bittorrent_peer_message);
|
||||
connection_state(S_TRANS),
|
||||
sent_bittorrent_peer_message);
|
||||
|
||||
done_string(&string);
|
||||
|
||||
@ -658,7 +659,8 @@ read_bittorrent_peer_data(struct socket *socket, struct read_buffer *buffer)
|
||||
break;
|
||||
|
||||
case BITTORRENT_STATE_OUT_OF_MEM:
|
||||
abort_connection(peer->bittorrent->conn, S_OUT_OF_MEM);
|
||||
abort_connection(peer->bittorrent->conn,
|
||||
connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
|
||||
case BITTORRENT_STATE_ERROR:
|
||||
@ -669,7 +671,8 @@ read_bittorrent_peer_data(struct socket *socket, struct read_buffer *buffer)
|
||||
}
|
||||
|
||||
/* Shutdown on fatal errors! */
|
||||
abort_connection(peer->bittorrent->conn, -write_errno);
|
||||
abort_connection(peer->bittorrent->conn,
|
||||
connection_state_for_errno(write_errno));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -710,7 +713,7 @@ sent_bittorrent_peer_handshake(struct socket *socket)
|
||||
send_bittorrent_peer_message(peer, BITTORRENT_MESSAGE_BITFIELD);
|
||||
}
|
||||
|
||||
read_from_socket(peer->socket, buffer, S_TRANS,
|
||||
read_from_socket(peer->socket, buffer, connection_state(S_TRANS),
|
||||
read_bittorrent_peer_data);
|
||||
}
|
||||
|
||||
@ -763,7 +766,8 @@ send_bittorrent_peer_handshake(struct socket *socket)
|
||||
* and we might want to hold on to the old buffer if the peer ID of the
|
||||
* handshake was not read. */
|
||||
write_to_socket(peer->socket, handshake, sizeof(handshake),
|
||||
S_TRANS, sent_bittorrent_peer_handshake);
|
||||
connection_state(S_TRANS),
|
||||
sent_bittorrent_peer_handshake);
|
||||
}
|
||||
|
||||
#if 0
|
||||
@ -935,7 +939,8 @@ do_read_bittorrent_peer_handshake(struct socket *socket, struct read_buffer *buf
|
||||
break;
|
||||
}
|
||||
|
||||
read_from_socket(peer->socket, buffer, S_TRANS,
|
||||
read_from_socket(peer->socket, buffer,
|
||||
connection_state(S_TRANS),
|
||||
read_bittorrent_peer_handshake);
|
||||
break;
|
||||
|
||||
@ -945,7 +950,8 @@ do_read_bittorrent_peer_handshake(struct socket *socket, struct read_buffer *buf
|
||||
|
||||
case BITTORRENT_PEER_HANDSHAKE_INCOMPLETE:
|
||||
/* The whole handshake was not read so wait for more. */
|
||||
read_from_socket(peer->socket, buffer, S_TRANS,
|
||||
read_from_socket(peer->socket, buffer,
|
||||
connection_state(S_TRANS),
|
||||
read_bittorrent_peer_handshake);
|
||||
break;
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ set_bittorrent_tracker_interval(struct connection *conn)
|
||||
/* XXX: The data pointer may be NULL when doing event=stopped because no
|
||||
* connection is attached anymore. */
|
||||
static void
|
||||
bittorrent_tracker_callback(void *data, enum connection_state state,
|
||||
bittorrent_tracker_callback(void *data, struct connection_state state,
|
||||
struct string *response)
|
||||
{
|
||||
struct connection *conn = data;
|
||||
@ -75,12 +75,12 @@ bittorrent_tracker_callback(void *data, enum connection_state state,
|
||||
|
||||
/* FIXME: We treat any error as fatal here, however, it might be better
|
||||
* to relax that and allow a few errors before ending the connection. */
|
||||
if (state != S_OK) {
|
||||
if (state == S_INTERRUPTED)
|
||||
if (!is_in_state(state, S_OK)) {
|
||||
if (is_in_state(state, S_INTERRUPTED))
|
||||
return;
|
||||
bittorrent->tracker.failed = 1;
|
||||
add_bittorrent_message(conn->uri, state, NULL);
|
||||
abort_connection(conn, S_OK);
|
||||
abort_connection(conn, connection_state(S_OK));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -102,16 +102,17 @@ bittorrent_tracker_callback(void *data, enum connection_state state,
|
||||
return;
|
||||
|
||||
case BITTORRENT_STATE_OUT_OF_MEM:
|
||||
state = S_OUT_OF_MEM;
|
||||
state = connection_state(S_OUT_OF_MEM);
|
||||
break;
|
||||
|
||||
case BITTORRENT_STATE_REQUEST_FAILURE:
|
||||
add_bittorrent_message(conn->uri, S_OK, response);
|
||||
state = S_OK;
|
||||
add_bittorrent_message(conn->uri, connection_state(S_OK),
|
||||
response);
|
||||
state = connection_state(S_OK);
|
||||
break;
|
||||
|
||||
default:
|
||||
state = S_BITTORRENT_TRACKER;
|
||||
state = connection_state(S_BITTORRENT_TRACKER);
|
||||
}
|
||||
|
||||
abort_connection(conn, state);
|
||||
@ -158,7 +159,8 @@ do_send_bittorrent_tracker_request(struct connection *conn)
|
||||
if (!init_string(&request)) {
|
||||
done_string(&request);
|
||||
if (!stopped)
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn,
|
||||
connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -169,7 +171,8 @@ do_send_bittorrent_tracker_request(struct connection *conn)
|
||||
if (!uri) {
|
||||
done_string(&request);
|
||||
if (!stopped)
|
||||
abort_connection(conn, S_BITTORRENT_ERROR);
|
||||
abort_connection(conn,
|
||||
connection_state(S_BITTORRENT_ERROR));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -246,7 +249,8 @@ do_send_bittorrent_tracker_request(struct connection *conn)
|
||||
done_string(&request);
|
||||
if (!uri) {
|
||||
if (!stopped)
|
||||
abort_connection(conn, S_BITTORRENT_ERROR);
|
||||
abort_connection(conn,
|
||||
connection_state(S_BITTORRENT_ERROR));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@ close_all_non_term_fd(void)
|
||||
close(n);
|
||||
}
|
||||
|
||||
enum connection_state
|
||||
struct connection_state
|
||||
init_directory_listing(struct string *page, struct uri *uri)
|
||||
{
|
||||
struct string dirpath = NULL_STRING;
|
||||
@ -151,5 +151,7 @@ out_of_memory:
|
||||
done_string(&decoded);
|
||||
done_string(&location);
|
||||
|
||||
return page->length > 0 ? S_OK : S_OUT_OF_MEM;
|
||||
return page->length > 0
|
||||
? connection_state(S_OK)
|
||||
: connection_state(S_OUT_OF_MEM);
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ struct uri;
|
||||
/* Close all non-terminal file descriptors. */
|
||||
void close_all_non_term_fd(void);
|
||||
|
||||
enum connection_state
|
||||
struct connection_state
|
||||
init_directory_listing(struct string *page, struct uri *uri);
|
||||
|
||||
#endif
|
||||
|
@ -120,7 +120,7 @@ data_protocol_handler(struct connection *conn)
|
||||
int base64 = 0;
|
||||
|
||||
if (!cached) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -128,7 +128,7 @@ data_protocol_handler(struct connection *conn)
|
||||
|
||||
data_start = parse_data_protocol_header(conn, &base64);
|
||||
if (!data_start) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -136,7 +136,7 @@ data_protocol_handler(struct connection *conn)
|
||||
* it. */
|
||||
data = memacpy(data_start, uri->datalen - (data_start - uri->data));
|
||||
if (!data) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -144,7 +144,7 @@ data_protocol_handler(struct connection *conn)
|
||||
unsigned char *decoded = base64_encode(data);
|
||||
|
||||
if (!decoded) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -163,5 +163,5 @@ data_protocol_handler(struct connection *conn)
|
||||
|
||||
mem_free(data);
|
||||
|
||||
abort_connection(conn, S_OK);
|
||||
abort_connection(conn, connection_state(S_OK));
|
||||
}
|
||||
|
@ -77,7 +77,8 @@ close_pipe_and_read(struct socket *data_socket)
|
||||
data_socket->fd = -1;
|
||||
|
||||
conn->socket->state = SOCKET_END_ONCLOSE;
|
||||
read_from_socket(conn->socket, rb, S_SENT, http_got_header);
|
||||
read_from_socket(conn->socket, rb, connection_state(S_SENT),
|
||||
http_got_header);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -91,7 +92,7 @@ send_post_data(struct connection *conn)
|
||||
int n = 0;
|
||||
|
||||
if (!init_string(&data)) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
postend = strchr(post, '\n');
|
||||
@ -125,7 +126,7 @@ send_post_data(struct connection *conn)
|
||||
* and an assertion would fail in write_to_socket. */
|
||||
if (data.length)
|
||||
write_to_socket(conn->data_socket, data.source, data.length,
|
||||
S_SENT, close_pipe_and_read);
|
||||
connection_state(S_SENT), close_pipe_and_read);
|
||||
else
|
||||
close_pipe_and_read(conn->data_socket);
|
||||
|
||||
@ -309,7 +310,7 @@ execute_cgi(struct connection *conn)
|
||||
int scriptlen;
|
||||
struct stat buf;
|
||||
pid_t pid;
|
||||
enum connection_state state = S_OK;
|
||||
struct connection_state state = connection_state(S_OK);
|
||||
int pipe_read[2], pipe_write[2];
|
||||
|
||||
if (!get_opt_bool("protocol.file.cgi.policy")) return 1;
|
||||
@ -321,7 +322,7 @@ execute_cgi(struct connection *conn)
|
||||
|
||||
script = get_uri_string(conn->uri, URI_PATH);
|
||||
if (!script) {
|
||||
state = S_OUT_OF_MEM;
|
||||
state = connection_state(S_OUT_OF_MEM);
|
||||
goto end2;
|
||||
}
|
||||
decode_uri(script);
|
||||
@ -353,13 +354,13 @@ execute_cgi(struct connection *conn)
|
||||
}
|
||||
|
||||
if (c_pipe(pipe_read) || c_pipe(pipe_write)) {
|
||||
state = -errno;
|
||||
state = connection_state_for_errno(errno);
|
||||
goto end1;
|
||||
}
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
state = -errno;
|
||||
state = connection_state_for_errno(errno);
|
||||
goto end0;
|
||||
}
|
||||
if (!pid) { /* CGI script */
|
||||
|
@ -174,33 +174,33 @@ add_dir_entries(struct directory_entry *entries, unsigned char *dirpath,
|
||||
/* Generates an HTML page listing the content of @directory with the path
|
||||
* @dirpath. */
|
||||
/* Returns a connection state. S_OK if all is well. */
|
||||
static inline enum connection_state
|
||||
static inline struct connection_state
|
||||
list_directory(struct connection *conn, unsigned char *dirpath,
|
||||
struct string *page)
|
||||
{
|
||||
int show_hidden_files = get_opt_bool("protocol.file.show_hidden_files");
|
||||
struct directory_entry *entries;
|
||||
enum connection_state state;
|
||||
struct connection_state state;
|
||||
|
||||
errno = 0;
|
||||
entries = get_directory_entries(dirpath, show_hidden_files);
|
||||
if (!entries) {
|
||||
if (errno) return -errno;
|
||||
return S_OUT_OF_MEM;
|
||||
if (errno) return connection_state_for_errno(errno);
|
||||
return connection_state(S_OUT_OF_MEM);
|
||||
}
|
||||
|
||||
state = init_directory_listing(page, conn->uri);
|
||||
if (state != S_OK)
|
||||
return S_OUT_OF_MEM;
|
||||
if (!is_in_state(state, S_OK))
|
||||
return connection_state(S_OUT_OF_MEM);
|
||||
|
||||
add_dir_entries(entries, dirpath, page);
|
||||
|
||||
if (!add_to_string(page, "</pre>\n<hr/>\n</body>\n</html>\n")) {
|
||||
done_string(page);
|
||||
return S_OUT_OF_MEM;
|
||||
return connection_state(S_OUT_OF_MEM);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
return connection_state(S_OK);
|
||||
}
|
||||
|
||||
|
||||
@ -215,13 +215,14 @@ file_protocol_handler(struct connection *connection)
|
||||
{
|
||||
unsigned char *redirect_location = NULL;
|
||||
struct string page, name;
|
||||
enum connection_state state;
|
||||
struct connection_state state;
|
||||
int set_dir_content_type = 0;
|
||||
|
||||
if (get_cmd_opt_bool("anonymous")) {
|
||||
if (strcmp(connection->uri->string, "file:///dev/stdin")
|
||||
|| isatty(STDIN_FILENO)) {
|
||||
abort_connection(connection, S_FILE_ANONYMOUS);
|
||||
abort_connection(connection,
|
||||
connection_state(S_FILE_ANONYMOUS));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -239,7 +240,7 @@ file_protocol_handler(struct connection *connection)
|
||||
if (!init_string(&name)
|
||||
|| !add_uri_to_string(&name, connection->uri, URI_PATH)) {
|
||||
done_string(&name);
|
||||
abort_connection(connection, S_OUT_OF_MEM);
|
||||
abort_connection(connection, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -254,7 +255,7 @@ file_protocol_handler(struct connection *connection)
|
||||
* directory separator. */
|
||||
if (name.source[0] && !dir_sep(name.source[name.length - 1])) {
|
||||
redirect_location = STRING_DIR_SEP;
|
||||
state = S_OK;
|
||||
state = connection_state(S_OK);
|
||||
} else {
|
||||
state = list_directory(connection, name.source, &page);
|
||||
set_dir_content_type = 1;
|
||||
@ -268,7 +269,7 @@ file_protocol_handler(struct connection *connection)
|
||||
|
||||
done_string(&name);
|
||||
|
||||
if (state == S_OK) {
|
||||
if (is_in_state(state, S_OK)) {
|
||||
struct cache_entry *cached;
|
||||
|
||||
/* Try to add fragment data to the connection cache if either
|
||||
@ -276,11 +277,11 @@ file_protocol_handler(struct connection *connection)
|
||||
cached = connection->cached = get_cache_entry(connection->uri);
|
||||
if (!connection->cached) {
|
||||
if (!redirect_location) done_string(&page);
|
||||
state = S_OUT_OF_MEM;
|
||||
state = connection_state(S_OUT_OF_MEM);
|
||||
|
||||
} else if (redirect_location) {
|
||||
if (!redirect_cache(cached, redirect_location, 1, 0))
|
||||
state = S_OUT_OF_MEM;
|
||||
state = connection_state(S_OUT_OF_MEM);
|
||||
|
||||
} else {
|
||||
add_fragment(cached, 0, page.source, page.length);
|
||||
@ -300,7 +301,7 @@ file_protocol_handler(struct connection *connection)
|
||||
/* Not so gracefully handle failed memory
|
||||
* allocation. */
|
||||
if (!head)
|
||||
state = S_OUT_OF_MEM;
|
||||
state = connection_state(S_OUT_OF_MEM);
|
||||
|
||||
/* Setup directory listing for viewing. */
|
||||
mem_free_set(&cached->head, head);
|
||||
|
@ -35,13 +35,13 @@ finger_get_response(struct socket *socket, struct read_buffer *rb)
|
||||
int l;
|
||||
|
||||
if (!cached) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
conn->cached = cached;
|
||||
|
||||
if (socket->state == SOCKET_CLOSED) {
|
||||
abort_connection(conn, S_OK);
|
||||
abort_connection(conn, connection_state(S_OK));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -53,7 +53,8 @@ finger_get_response(struct socket *socket, struct read_buffer *rb)
|
||||
|
||||
conn->from += l;
|
||||
kill_buffer_data(rb, l);
|
||||
read_from_socket(conn->socket, rb, S_TRANS, finger_get_response);
|
||||
read_from_socket(conn->socket, rb, connection_state(S_TRANS),
|
||||
finger_get_response);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -70,7 +71,8 @@ finger_send_request(struct socket *socket)
|
||||
add_bytes_to_string(&req, conn->uri->user, conn->uri->userlen);
|
||||
}
|
||||
add_crlf_to_string(&req);
|
||||
request_from_socket(socket, req.source, req.length, S_SENT,
|
||||
request_from_socket(socket, req.source, req.length,
|
||||
connection_state(S_SENT),
|
||||
SOCKET_END_ONCLOSE, finger_get_response);
|
||||
done_string(&req);
|
||||
}
|
||||
|
@ -74,11 +74,11 @@ struct module fsp_protocol_module = struct_module(
|
||||
*
|
||||
* - If an error occurs, the child process writes "text/x-error"
|
||||
* without newline to stderr, and an error code and a newline to
|
||||
* stdout. The error code is either from errno or a negated value
|
||||
* from enum connection_state, e.g. -S_OUT_OF_MEM. In particular,
|
||||
* EPERM causes the parent process to prompt for username and
|
||||
* password. (In this, fsplib differs from libsmbclient, which uses
|
||||
* EACCES if authentication fails.)
|
||||
* stdout. The error code is either "S" followed by errno or "I"
|
||||
* followed by enum connection_basic_state. In particular, EPERM
|
||||
* causes the parent process to prompt for username and password.
|
||||
* (In this, fsplib differs from libsmbclient, which uses EACCES if
|
||||
* authentication fails.)
|
||||
*
|
||||
* - If the resource is a regular file, the child process writes the
|
||||
* estimated length of the file (in bytes) and a newline to stderr,
|
||||
@ -103,9 +103,12 @@ struct module fsp_protocol_module = struct_module(
|
||||
* stdout fails for directory listing like we do for file fetching. */
|
||||
|
||||
static void
|
||||
fsp_error(int error)
|
||||
fsp_error(struct connection_state error)
|
||||
{
|
||||
printf("%d\n", error);
|
||||
if (is_system_error(error))
|
||||
printf("S%d\n", (int) error.syserr);
|
||||
else
|
||||
printf("I%d\n", (int) error.basic);
|
||||
fprintf(stderr, "text/x-error");
|
||||
/* In principle, this should perhaps call fsp_close_session to
|
||||
* make the server accept any key from the next client process
|
||||
@ -215,13 +218,13 @@ fsp_directory(FSP_SESSION *ses, struct uri *uri)
|
||||
unsigned char dircolor[8] = "";
|
||||
|
||||
if (!data)
|
||||
fsp_error(-S_OUT_OF_MEM);
|
||||
fsp_error(connection_state(S_OUT_OF_MEM));
|
||||
decode_uri(data);
|
||||
if (init_directory_listing(&buf, uri) != S_OK)
|
||||
fsp_error(-S_OUT_OF_MEM);
|
||||
if (!is_in_state(init_directory_listing(&buf, uri), S_OK))
|
||||
fsp_error(connection_state(S_OUT_OF_MEM));
|
||||
|
||||
dir = fsp_opendir(ses, data);
|
||||
if (!dir) fsp_error(errno);
|
||||
if (!dir) fsp_error(connection_state_for_errno(errno));
|
||||
|
||||
fprintf(stderr, "text/html");
|
||||
fclose(stderr);
|
||||
@ -275,7 +278,7 @@ do_fsp(struct connection *conn)
|
||||
}
|
||||
|
||||
ses = fsp_open_session(host, port, password);
|
||||
if (!ses) fsp_error(errno);
|
||||
if (!ses) fsp_error(connection_state_for_errno(errno));
|
||||
|
||||
/* fsplib 0.8 ABI depends on _FILE_OFFSET_BITS
|
||||
* https://sourceforge.net/tracker/index.php?func=detail&aid=1674729&group_id=93841&atid=605738
|
||||
@ -295,7 +298,7 @@ do_fsp(struct connection *conn)
|
||||
* sb.st_size really needs to be filled, but filling the rest
|
||||
* too helps viewing the data with a debugger.) */
|
||||
memset(&sb, 0xAA, sizeof(sb));
|
||||
if (fsp_stat(ses, data, &sb)) fsp_error(errno);
|
||||
if (fsp_stat(ses, data, &sb)) fsp_error(connection_state_for_errno(errno));
|
||||
|
||||
if (S_ISDIR(sb.st_mode)) {
|
||||
fsp_directory(ses, uri);
|
||||
@ -305,7 +308,7 @@ do_fsp(struct connection *conn)
|
||||
int r;
|
||||
|
||||
if (!file) {
|
||||
fsp_error(errno);
|
||||
fsp_error(connection_state_for_errno(errno));
|
||||
}
|
||||
|
||||
#if SIZEOF_OFF_T >= 8
|
||||
@ -359,7 +362,7 @@ static void
|
||||
prompt_username_pw(struct connection *conn)
|
||||
{
|
||||
add_auth_entry(conn->uri, "FSP", NULL, NULL, 0);
|
||||
abort_connection(conn, S_OK);
|
||||
abort_connection(conn, connection_state(S_OK));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -367,10 +370,10 @@ fsp_got_error(struct socket *socket, struct read_buffer *rb)
|
||||
{
|
||||
int len = rb->length;
|
||||
struct connection *conn = socket->conn;
|
||||
int error;
|
||||
struct connection_state error;
|
||||
|
||||
if (len < 0) {
|
||||
abort_connection(conn, -errno);
|
||||
abort_connection(conn, connection_state_for_errno(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -380,20 +383,28 @@ fsp_got_error(struct socket *socket, struct read_buffer *rb)
|
||||
* pipe. */
|
||||
assert(rb->freespace >= 1);
|
||||
if_assert_failed {
|
||||
abort_connection(conn, S_INTERNAL);
|
||||
abort_connection(conn, connection_state(S_INTERNAL));
|
||||
return;
|
||||
}
|
||||
rb->data[len] = '\0';
|
||||
error = atoi(rb->data);
|
||||
kill_buffer_data(rb, len);
|
||||
switch (error) {
|
||||
case EPERM:
|
||||
prompt_username_pw(conn);
|
||||
switch (rb->data[0]) {
|
||||
case 'S':
|
||||
error = connection_state_for_errno(atoi(rb->data + 1));
|
||||
break;
|
||||
case 'I':
|
||||
error = connection_state(atoi(rb->data + 1));
|
||||
break;
|
||||
default:
|
||||
abort_connection(conn, -error);
|
||||
ERROR("malformed error code: %s", rb->data);
|
||||
error = connection_state(S_INTERNAL);
|
||||
break;
|
||||
}
|
||||
kill_buffer_data(rb, len);
|
||||
|
||||
if (is_system_error(error) && error.syserr == EPERM)
|
||||
prompt_username_pw(conn);
|
||||
else
|
||||
abort_connection(conn, error);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -403,12 +414,12 @@ fsp_got_data(struct socket *socket, struct read_buffer *rb)
|
||||
struct connection *conn = socket->conn;
|
||||
|
||||
if (len < 0) {
|
||||
abort_connection(conn, -errno);
|
||||
abort_connection(conn, connection_state_for_errno(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!len) {
|
||||
abort_connection(conn, S_OK);
|
||||
abort_connection(conn, connection_state(S_OK));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -419,7 +430,7 @@ fsp_got_data(struct socket *socket, struct read_buffer *rb)
|
||||
conn->from += len;
|
||||
kill_buffer_data(rb, len);
|
||||
|
||||
read_from_socket(socket, rb, S_TRANS, fsp_got_data);
|
||||
read_from_socket(socket, rb, connection_state(S_TRANS), fsp_got_data);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -438,7 +449,7 @@ fsp_got_header(struct socket *socket, struct read_buffer *rb)
|
||||
* and assume abort_connection will do them?) */
|
||||
close_socket(socket);
|
||||
close_socket(conn->data_socket);
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
socket->state = SOCKET_END_ONCLOSE;
|
||||
@ -461,7 +472,7 @@ fsp_got_header(struct socket *socket, struct read_buffer *rb)
|
||||
|
||||
/* avoid read from socket error */
|
||||
if (!conn->est_length) {
|
||||
abort_connection(conn, S_OK);
|
||||
abort_connection(conn, connection_state(S_OK));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -476,15 +487,17 @@ fsp_got_header(struct socket *socket, struct read_buffer *rb)
|
||||
if (!buf) {
|
||||
close_socket(socket);
|
||||
close_socket(conn->data_socket);
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
mem_free_set(&conn->cached->content_type, stracpy("text/html"));
|
||||
read_from_socket(conn->data_socket, buf, S_CONN, fsp_got_error);
|
||||
read_from_socket(conn->data_socket, buf,
|
||||
connection_state(S_CONN), fsp_got_error);
|
||||
} else {
|
||||
read_from_socket(conn->data_socket, buf, S_CONN, fsp_got_data);
|
||||
read_from_socket(conn->data_socket, buf,
|
||||
connection_state(S_CONN), fsp_got_data);
|
||||
}
|
||||
}
|
||||
|
||||
@ -503,7 +516,7 @@ fsp_protocol_handler(struct connection *conn)
|
||||
if (fsp_pipe[1] >= 0) close(fsp_pipe[1]);
|
||||
if (header_pipe[0] >= 0) close(header_pipe[0]);
|
||||
if (header_pipe[1] >= 0) close(header_pipe[1]);
|
||||
abort_connection(conn, -s_errno);
|
||||
abort_connection(conn, connection_state_for_errno(s_errno));
|
||||
return;
|
||||
}
|
||||
conn->from = 0;
|
||||
@ -518,7 +531,7 @@ fsp_protocol_handler(struct connection *conn)
|
||||
close(fsp_pipe[1]);
|
||||
close(header_pipe[0]);
|
||||
close(header_pipe[1]);
|
||||
retry_connection(conn, -s_errno);
|
||||
retry_connection(conn, connection_state_for_errno(s_errno));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -556,9 +569,10 @@ fsp_protocol_handler(struct connection *conn)
|
||||
if (!buf2) {
|
||||
close_socket(conn->data_socket);
|
||||
close_socket(conn->socket);
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
read_from_socket(conn->socket, buf2, S_CONN, fsp_got_header);
|
||||
read_from_socket(conn->socket, buf2,
|
||||
connection_state(S_CONN), fsp_got_header);
|
||||
}
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ struct ftp_connection_info {
|
||||
|
||||
/* Prototypes */
|
||||
static void ftp_login(struct socket *);
|
||||
static void ftp_send_retr_req(struct connection *, int);
|
||||
static void ftp_send_retr_req(struct connection *, struct connection_state);
|
||||
static void ftp_got_info(struct socket *, struct read_buffer *);
|
||||
static void ftp_got_user_info(struct socket *, struct read_buffer *);
|
||||
static void ftp_pass(struct connection *);
|
||||
@ -127,7 +127,7 @@ static void ftp_pass_info(struct socket *, struct read_buffer *);
|
||||
static void ftp_retr_file(struct socket *, struct read_buffer *);
|
||||
static void ftp_got_final_response(struct socket *, struct read_buffer *);
|
||||
static void got_something_from_data_connection(struct connection *);
|
||||
static void ftp_end_request(struct connection *, enum connection_state);
|
||||
static void ftp_end_request(struct connection *, struct connection_state);
|
||||
static struct ftp_connection_info *add_file_cmd_to_str(struct connection *);
|
||||
static void ftp_data_accept(struct connection *conn);
|
||||
|
||||
@ -276,13 +276,14 @@ ftp_protocol_handler(struct connection *conn)
|
||||
conn->cache_mode >= CACHE_MODE_FORCE_RELOAD);
|
||||
|
||||
} else {
|
||||
ftp_send_retr_req(conn, S_SENT);
|
||||
ftp_send_retr_req(conn, connection_state(S_SENT));
|
||||
}
|
||||
}
|
||||
|
||||
/* Send command, set connection state and free cmd string. */
|
||||
static void
|
||||
send_cmd(struct connection *conn, struct string *cmd, void *callback, int state)
|
||||
send_cmd(struct connection *conn, struct string *cmd, void *callback,
|
||||
struct connection_state state)
|
||||
{
|
||||
request_from_socket(conn->socket, cmd->source, cmd->length, state,
|
||||
SOCKET_RETRY_ONCLOSE, callback);
|
||||
@ -308,20 +309,20 @@ prompt_username_pw(struct connection *conn)
|
||||
if (!conn->cached) {
|
||||
conn->cached = get_cache_entry(conn->uri);
|
||||
if (!conn->cached) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mem_free_set(&conn->cached->content_type, stracpy("text/html"));
|
||||
if (!conn->cached->content_type) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
add_auth_entry(conn->uri, "FTP Login", NULL, NULL, 0);
|
||||
|
||||
abort_connection(conn, S_OK);
|
||||
abort_connection(conn, connection_state(S_OK));
|
||||
}
|
||||
|
||||
/* Send USER command. */
|
||||
@ -335,7 +336,7 @@ ftp_login(struct socket *socket)
|
||||
auth = find_auth(conn->uri);
|
||||
|
||||
if (!init_string(&cmd)) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -353,7 +354,7 @@ ftp_login(struct socket *socket)
|
||||
}
|
||||
add_crlf_to_string(&cmd);
|
||||
|
||||
send_cmd(conn, &cmd, (void *) ftp_got_info, S_SENT);
|
||||
send_cmd(conn, &cmd, (void *) ftp_got_info, connection_state(S_SENT));
|
||||
}
|
||||
|
||||
/* Parse connection response. */
|
||||
@ -364,7 +365,7 @@ ftp_got_info(struct socket *socket, struct read_buffer *rb)
|
||||
int response = get_ftp_response(conn, rb, 0, NULL);
|
||||
|
||||
if (response == -1) {
|
||||
abort_connection(conn, S_FTP_ERROR);
|
||||
abort_connection(conn, connection_state(S_FTP_ERROR));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -380,7 +381,7 @@ ftp_got_info(struct socket *socket, struct read_buffer *rb)
|
||||
|
||||
if (response != 220) {
|
||||
/* TODO? Retry in case of ... ?? */
|
||||
retry_connection(conn, S_FTP_UNAVAIL);
|
||||
retry_connection(conn, connection_state(S_FTP_UNAVAIL));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -396,7 +397,7 @@ ftp_got_user_info(struct socket *socket, struct read_buffer *rb)
|
||||
int response = get_ftp_response(conn, rb, 0, NULL);
|
||||
|
||||
if (response == -1) {
|
||||
abort_connection(conn, S_FTP_ERROR);
|
||||
abort_connection(conn, connection_state(S_FTP_ERROR));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -426,12 +427,12 @@ ftp_got_user_info(struct socket *socket, struct read_buffer *rb)
|
||||
* non-RFC compliant servers may return even something other than 421.
|
||||
* --Zas */
|
||||
if (response >= 400) {
|
||||
abort_connection(conn, S_FTP_UNAVAIL);
|
||||
abort_connection(conn, connection_state(S_FTP_UNAVAIL));
|
||||
return;
|
||||
}
|
||||
|
||||
if (response == 230) {
|
||||
ftp_send_retr_req(conn, S_GETH);
|
||||
ftp_send_retr_req(conn, connection_state(S_GETH));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -448,7 +449,7 @@ ftp_pass(struct connection *conn)
|
||||
auth = find_auth(conn->uri);
|
||||
|
||||
if (!init_string(&cmd)) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -470,7 +471,7 @@ ftp_pass(struct connection *conn)
|
||||
}
|
||||
add_crlf_to_string(&cmd);
|
||||
|
||||
send_cmd(conn, &cmd, (void *) ftp_pass_info, S_LOGIN);
|
||||
send_cmd(conn, &cmd, (void *) ftp_pass_info, connection_state(S_LOGIN));
|
||||
}
|
||||
|
||||
/* Parse PASS command response. */
|
||||
@ -481,12 +482,13 @@ ftp_pass_info(struct socket *socket, struct read_buffer *rb)
|
||||
int response = get_ftp_response(conn, rb, 0, NULL);
|
||||
|
||||
if (response == -1) {
|
||||
abort_connection(conn, S_FTP_ERROR);
|
||||
abort_connection(conn, connection_state(S_FTP_ERROR));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!response) {
|
||||
read_from_socket(conn->socket, rb, S_LOGIN, ftp_pass_info);
|
||||
read_from_socket(conn->socket, rb, connection_state(S_LOGIN),
|
||||
ftp_pass_info);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -508,11 +510,11 @@ ftp_pass_info(struct socket *socket, struct read_buffer *rb)
|
||||
}
|
||||
|
||||
if (response >= 400) {
|
||||
abort_connection(conn, S_FTP_UNAVAIL);
|
||||
abort_connection(conn, connection_state(S_FTP_UNAVAIL));
|
||||
return;
|
||||
}
|
||||
|
||||
ftp_send_retr_req(conn, S_GETH);
|
||||
ftp_send_retr_req(conn, connection_state(S_GETH));
|
||||
}
|
||||
|
||||
/* Construct PORT command. */
|
||||
@ -673,7 +675,7 @@ add_file_cmd_to_str(struct connection *conn)
|
||||
|
||||
if (!conn->uri->data) {
|
||||
INTERNAL("conn->uri->data empty");
|
||||
abort_connection(conn, S_INTERNAL);
|
||||
abort_connection(conn, connection_state(S_INTERNAL));
|
||||
goto ret;
|
||||
}
|
||||
|
||||
@ -684,7 +686,7 @@ add_file_cmd_to_str(struct connection *conn)
|
||||
* risky. */
|
||||
ftp = mem_calloc(1, sizeof(*ftp));
|
||||
if (!ftp) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
goto ret;
|
||||
}
|
||||
|
||||
@ -693,24 +695,24 @@ add_file_cmd_to_str(struct connection *conn)
|
||||
if (!init_string(&command)
|
||||
|| !init_string(&ftp_data_command)
|
||||
|| !init_string(&pathname)) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
goto ret;
|
||||
}
|
||||
|
||||
if (!get_ftp_data_socket(conn, &ftp_data_command)) {
|
||||
INTERNAL("Ftp data socket failure");
|
||||
abort_connection(conn, S_INTERNAL);
|
||||
abort_connection(conn, connection_state(S_INTERNAL));
|
||||
goto ret;
|
||||
}
|
||||
|
||||
if (!add_uri_to_string(&pathname, conn->uri, URI_PATH)) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
goto ret;
|
||||
}
|
||||
|
||||
decode_uri_string(&pathname);
|
||||
if (!is_ftp_pathname_safe(&pathname)) {
|
||||
abort_connection(conn, S_BAD_URL);
|
||||
abort_connection(conn, connection_state(S_BAD_URL));
|
||||
goto ret;
|
||||
}
|
||||
|
||||
@ -732,7 +734,7 @@ add_file_cmd_to_str(struct connection *conn)
|
||||
|
||||
|| !add_to_string(&command, "LIST")
|
||||
|| !add_crlf_to_string(&command)) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
goto ret;
|
||||
}
|
||||
|
||||
@ -748,7 +750,7 @@ add_file_cmd_to_str(struct connection *conn)
|
||||
|| !add_crlf_to_string(&command)
|
||||
|
||||
|| !add_string_to_string(&command, &ftp_data_command)) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
goto ret;
|
||||
}
|
||||
|
||||
@ -760,7 +762,7 @@ add_file_cmd_to_str(struct connection *conn)
|
||||
if (!add_to_string(&command, "REST ")
|
||||
|| !add_long_to_string(&command, offset)
|
||||
|| !add_crlf_to_string(&command)) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
goto ret;
|
||||
}
|
||||
|
||||
@ -771,7 +773,7 @@ add_file_cmd_to_str(struct connection *conn)
|
||||
if (!add_to_string(&command, "RETR ")
|
||||
|| !add_string_to_string(&command, &pathname)
|
||||
|| !add_crlf_to_string(&command)) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
goto ret;
|
||||
}
|
||||
}
|
||||
@ -781,7 +783,7 @@ add_file_cmd_to_str(struct connection *conn)
|
||||
/* 1 byte is already reserved for cmd_buffer in struct ftp_connection_info. */
|
||||
ftp = mem_realloc(ftp, sizeof(*ftp) + command.length);
|
||||
if (!ftp) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
goto ret;
|
||||
}
|
||||
conn->info = ftp; /* in case mem_realloc moved the buffer */
|
||||
@ -816,12 +818,12 @@ send_it_line_by_line(struct connection *conn, struct string *cmd)
|
||||
|
||||
/* Send commands to retrieve file or directory. */
|
||||
static void
|
||||
ftp_send_retr_req(struct connection *conn, int state)
|
||||
ftp_send_retr_req(struct connection *conn, struct connection_state state)
|
||||
{
|
||||
struct string cmd;
|
||||
|
||||
if (!init_string(&cmd)) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -916,13 +918,13 @@ ftp_data_connect(struct connection *conn, int pf, struct sockaddr_storage *sa,
|
||||
if (conn->data_socket->fd != -1) {
|
||||
/* The server maliciously sent multiple 227 or 229
|
||||
* responses. Do not leak the previous data_socket. */
|
||||
abort_connection(conn, S_FTP_ERROR);
|
||||
abort_connection(conn, connection_state(S_FTP_ERROR));
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd = socket(pf, SOCK_STREAM, 0);
|
||||
if (fd < 0 || set_nonblocking_fd(fd) < 0) {
|
||||
abort_connection(conn, S_FTP_ERROR);
|
||||
abort_connection(conn, connection_state(S_FTP_ERROR));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -947,12 +949,14 @@ ftp_retr_file(struct socket *socket, struct read_buffer *rb)
|
||||
response = get_ftp_response(conn, rb, 0, &sa);
|
||||
|
||||
if (response == -1) {
|
||||
abort_connection(conn, S_FTP_ERROR);
|
||||
abort_connection(conn, connection_state(S_FTP_ERROR));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!response) {
|
||||
read_from_socket(conn->socket, rb, S_GETH, ftp_retr_file);
|
||||
read_from_socket(conn->socket, rb,
|
||||
connection_state(S_GETH),
|
||||
ftp_retr_file);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -977,7 +981,8 @@ ftp_retr_file(struct socket *socket, struct read_buffer *rb)
|
||||
|
||||
case 2: /* PORT */
|
||||
if (response >= 400) {
|
||||
abort_connection(conn, S_FTP_PORT);
|
||||
abort_connection(conn,
|
||||
connection_state(S_FTP_PORT));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@ -986,7 +991,7 @@ ftp_retr_file(struct socket *socket, struct read_buffer *rb)
|
||||
if (response >= 400) {
|
||||
if (ftp->dir) {
|
||||
abort_connection(conn,
|
||||
S_FTP_NO_FILE);
|
||||
connection_state(S_FTP_NO_FILE));
|
||||
return;
|
||||
}
|
||||
conn->from = 0;
|
||||
@ -1010,19 +1015,20 @@ ftp_retr_file(struct socket *socket, struct read_buffer *rb)
|
||||
INTERNAL("WHAT???");
|
||||
}
|
||||
|
||||
ftp_send_retr_req(conn, S_GETH);
|
||||
ftp_send_retr_req(conn, connection_state(S_GETH));
|
||||
return;
|
||||
}
|
||||
|
||||
response = get_ftp_response(conn, rb, 2, NULL);
|
||||
|
||||
if (response == -1) {
|
||||
abort_connection(conn, S_FTP_ERROR);
|
||||
abort_connection(conn, connection_state(S_FTP_ERROR));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!response) {
|
||||
read_from_socket(conn->socket, rb, S_GETH, ftp_retr_file);
|
||||
read_from_socket(conn->socket, rb, connection_state(S_GETH),
|
||||
ftp_retr_file);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1057,7 +1063,7 @@ ftp_retr_file(struct socket *socket, struct read_buffer *rb)
|
||||
* get_ftp_data_socket would have created the
|
||||
* data_socket without waiting for anything from the
|
||||
* server. */
|
||||
abort_connection(conn, S_FTP_ERROR);
|
||||
abort_connection(conn, connection_state(S_FTP_ERROR));
|
||||
return;
|
||||
}
|
||||
set_handlers(conn->data_socket->fd, (select_handler_T) ftp_data_accept,
|
||||
@ -1075,13 +1081,13 @@ ftp_got_final_response(struct socket *socket, struct read_buffer *rb)
|
||||
int response = get_ftp_response(conn, rb, 0, NULL);
|
||||
|
||||
if (response == -1) {
|
||||
abort_connection(conn, S_FTP_ERROR);
|
||||
abort_connection(conn, connection_state(S_FTP_ERROR));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!response) {
|
||||
enum connection_state state = conn->state != S_TRANS
|
||||
? S_GETH : conn->state;
|
||||
struct connection_state state = !is_in_state(conn->state, S_TRANS)
|
||||
? connection_state(S_GETH) : conn->state;
|
||||
|
||||
read_from_socket(conn->socket, rb, state, ftp_got_final_response);
|
||||
return;
|
||||
@ -1096,25 +1102,25 @@ ftp_got_final_response(struct socket *socket, struct read_buffer *rb)
|
||||
|
||||
if (!conn->cached
|
||||
|| !redirect_cache(conn->cached, "/", 1, 0)) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
abort_connection(conn, S_OK);
|
||||
abort_connection(conn, connection_state(S_OK));
|
||||
return;
|
||||
}
|
||||
|
||||
if (response >= 400) {
|
||||
abort_connection(conn, S_FTP_FILE_ERROR);
|
||||
abort_connection(conn, connection_state(S_FTP_FILE_ERROR));
|
||||
return;
|
||||
}
|
||||
|
||||
if (ftp->conn_state == 2) {
|
||||
ftp_end_request(conn, S_OK);
|
||||
ftp_end_request(conn, connection_state(S_OK));
|
||||
} else {
|
||||
ftp->conn_state = 1;
|
||||
if (conn->state != S_TRANS)
|
||||
set_connection_state(conn, S_GETH);
|
||||
if (!is_in_state(conn->state, S_TRANS))
|
||||
set_connection_state(conn, connection_state(S_GETH));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1359,7 +1365,7 @@ ftp_data_accept(struct connection *conn)
|
||||
} else {
|
||||
newsock = accept(conn->data_socket->fd, NULL, NULL);
|
||||
if (newsock < 0) {
|
||||
retry_connection(conn, -errno);
|
||||
retry_connection(conn, connection_state_for_errno(errno));
|
||||
return;
|
||||
}
|
||||
close(conn->data_socket->fd);
|
||||
@ -1395,7 +1401,7 @@ got_something_from_data_connection(struct connection *conn)
|
||||
if (!conn->cached) conn->cached = get_cache_entry(conn->uri);
|
||||
if (!conn->cached) {
|
||||
out_of_mem:
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1412,15 +1418,15 @@ out_of_mem:
|
||||
|
||||
if (ftp->dir && !conn->from) {
|
||||
struct string string;
|
||||
enum connection_state state;
|
||||
struct connection_state state;
|
||||
|
||||
if (!conn->uri->data) {
|
||||
abort_connection(conn, S_FTP_ERROR);
|
||||
abort_connection(conn, connection_state(S_FTP_ERROR));
|
||||
return;
|
||||
}
|
||||
|
||||
state = init_directory_listing(&string, conn->uri);
|
||||
if (state != S_OK) {
|
||||
if (!is_in_state(state, S_OK)) {
|
||||
abort_connection(conn, state);
|
||||
return;
|
||||
}
|
||||
@ -1443,7 +1449,7 @@ out_of_mem:
|
||||
len = safe_read(conn->data_socket->fd, ftp->ftp_buffer + ftp->buf_pos,
|
||||
FTP_BUF_SIZE - ftp->buf_pos);
|
||||
if (len < 0) {
|
||||
retry_connection(conn, -errno);
|
||||
retry_connection(conn, connection_state_for_errno(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1475,7 +1481,7 @@ out_of_mem:
|
||||
|
||||
}
|
||||
|
||||
set_connection_state(conn, S_TRANS);
|
||||
set_connection_state(conn, connection_state(S_TRANS));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1493,17 +1499,17 @@ out_of_mem:
|
||||
close_socket(conn->data_socket);
|
||||
|
||||
if (ftp->conn_state == 1) {
|
||||
ftp_end_request(conn, S_OK);
|
||||
ftp_end_request(conn, connection_state(S_OK));
|
||||
} else {
|
||||
ftp->conn_state = 2;
|
||||
set_connection_state(conn, S_TRANS);
|
||||
set_connection_state(conn, connection_state(S_TRANS));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ftp_end_request(struct connection *conn, enum connection_state state)
|
||||
ftp_end_request(struct connection *conn, struct connection_state state)
|
||||
{
|
||||
if (state == S_OK && conn->cached) {
|
||||
if (is_in_state(state, S_OK) && conn->cached) {
|
||||
normalize_cache_entry(conn->cached, conn->from);
|
||||
}
|
||||
|
||||
|
@ -197,9 +197,9 @@ add_uri_decoded(struct string *command, unsigned char *string, int length,
|
||||
command->length = strlen(command->source);
|
||||
}
|
||||
|
||||
static enum connection_state init_gopher_index_cache_entry(struct connection *conn);
|
||||
static struct connection_state init_gopher_index_cache_entry(struct connection *conn);
|
||||
|
||||
static enum connection_state
|
||||
static struct connection_state
|
||||
add_gopher_command(struct connection *conn, struct string *command,
|
||||
enum gopher_entity entity,
|
||||
unsigned char *selector, int selectorlen)
|
||||
@ -269,11 +269,11 @@ add_gopher_command(struct connection *conn, struct string *command,
|
||||
return S_CONN;
|
||||
}
|
||||
|
||||
static enum connection_state
|
||||
static struct connection_state
|
||||
init_gopher_connection_info(struct connection *conn)
|
||||
{
|
||||
struct gopher_connection_info *gopher;
|
||||
enum connection_state state;
|
||||
struct connection_state state;
|
||||
struct string command;
|
||||
enum gopher_entity entity = DEFAULT_GOPHER_ENTITY;
|
||||
unsigned char *selector = conn->uri->data;
|
||||
@ -569,15 +569,15 @@ check_gopher_last_line(unsigned char *line, unsigned char *end)
|
||||
}
|
||||
|
||||
/* Parse a Gopher Menu document */
|
||||
static enum connection_state
|
||||
static struct connection_state
|
||||
read_gopher_directory_data(struct connection *conn, struct read_buffer *rb)
|
||||
{
|
||||
enum connection_state state = S_TRANS;
|
||||
struct connection_state state = connection_state(S_TRANS);
|
||||
struct string buffer;
|
||||
unsigned char *end;
|
||||
|
||||
if (conn->from == 0) {
|
||||
enum connection_state state;
|
||||
struct connection_state state;
|
||||
|
||||
state = init_directory_listing(&buffer, conn->uri);
|
||||
if (state != S_OK)
|
||||
@ -638,7 +638,7 @@ init_gopher_cache_entry(struct connection *conn)
|
||||
}
|
||||
|
||||
/* Display a Gopher Index document. */
|
||||
static enum connection_state
|
||||
static struct connection_state
|
||||
init_gopher_index_cache_entry(struct connection *conn)
|
||||
{
|
||||
unsigned char *where;
|
||||
@ -688,7 +688,7 @@ read_gopher_response_data(struct socket *socket, struct read_buffer *rb)
|
||||
{
|
||||
struct connection *conn = socket->conn;
|
||||
struct gopher_connection_info *gopher = conn->info;
|
||||
enum connection_state state = S_TRANS;
|
||||
struct connection_state state = S_TRANS;
|
||||
|
||||
assert(gopher && gopher->entity);
|
||||
|
||||
@ -767,7 +767,7 @@ void
|
||||
gopher_protocol_handler(struct connection *conn)
|
||||
{
|
||||
struct uri *uri = conn->uri;
|
||||
enum connection_state state = S_CONN;
|
||||
struct connection_state state = S_CONN;
|
||||
|
||||
switch (get_uri_port(uri)) {
|
||||
case 105:
|
||||
|
@ -469,7 +469,7 @@ check_http_server_bugs(struct uri *uri, struct http_connection_info *http,
|
||||
}
|
||||
|
||||
static void
|
||||
http_end_request(struct connection *conn, enum connection_state state,
|
||||
http_end_request(struct connection *conn, struct connection_state state,
|
||||
int notrunc)
|
||||
{
|
||||
shutdown_connection_stream(conn);
|
||||
@ -478,7 +478,7 @@ http_end_request(struct connection *conn, enum connection_state state,
|
||||
&& (!conn->socket->ssl) /* We won't keep alive ssl connections */
|
||||
&& (!get_opt_bool("protocol.http.bugs.post_no_keepalive")
|
||||
|| !conn->uri->post)) {
|
||||
if (state == S_OK && conn->cached)
|
||||
if (is_in_state(state, S_OK) && conn->cached)
|
||||
normalize_cache_entry(conn->cached, !notrunc ? conn->from : -1);
|
||||
set_connection_state(conn, state);
|
||||
add_keepalive_connection(conn, HTTP_KEEPALIVE_TIMEOUT, NULL);
|
||||
@ -520,7 +520,7 @@ init_http_connection_info(struct connection *conn, int major, int minor, int clo
|
||||
|
||||
http = mem_calloc(1, sizeof(*http));
|
||||
if (!http) {
|
||||
http_end_request(conn, S_OUT_OF_MEM, 0);
|
||||
http_end_request(conn, connection_state(S_OUT_OF_MEM), 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -587,7 +587,7 @@ http_send_header(struct socket *socket)
|
||||
|
||||
/* Sanity check for a host */
|
||||
if (!uri || !uri->host || !*uri->host || !uri->hostlen) {
|
||||
http_end_request(conn, S_BAD_URL, 0);
|
||||
http_end_request(conn, connection_state(S_BAD_URL), 0);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -595,7 +595,7 @@ http_send_header(struct socket *socket)
|
||||
if (!http) return;
|
||||
|
||||
if (!init_string(&header)) {
|
||||
http_end_request(conn, S_OUT_OF_MEM, 0);
|
||||
http_end_request(conn, connection_state(S_OUT_OF_MEM), 0);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -980,7 +980,8 @@ http_send_header(struct socket *socket)
|
||||
#undef POST_BUFFER_SIZE
|
||||
}
|
||||
|
||||
request_from_socket(socket, header.source, header.length, S_SENT,
|
||||
request_from_socket(socket, header.source, header.length,
|
||||
connection_state(S_SENT),
|
||||
SOCKET_END_ONCLOSE, http_got_header);
|
||||
done_string(&header);
|
||||
}
|
||||
@ -1130,7 +1131,8 @@ static void
|
||||
read_more_http_data(struct connection *conn, struct read_buffer *rb,
|
||||
int already_got_anything)
|
||||
{
|
||||
enum connection_state state = already_got_anything ? S_TRANS : conn->state;
|
||||
struct connection_state state = already_got_anything
|
||||
? connection_state(S_TRANS) : conn->state;
|
||||
|
||||
read_from_socket(conn->socket, rb, state, read_http_data);
|
||||
}
|
||||
@ -1155,7 +1157,7 @@ read_http_data_done(struct connection *conn)
|
||||
}
|
||||
}
|
||||
|
||||
http_end_request(conn, S_OK, 0);
|
||||
http_end_request(conn, connection_state(S_OK), 0);
|
||||
}
|
||||
|
||||
/* Returns:
|
||||
@ -1347,7 +1349,7 @@ read_http_data(struct socket *socket, struct read_buffer *rb)
|
||||
break;
|
||||
default:
|
||||
assertm(ret == -1, "Unexpected return value: %d", ret);
|
||||
abort_connection(conn, S_HTTP_ERROR);
|
||||
abort_connection(conn, connection_state(S_HTTP_ERROR));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1454,7 +1456,9 @@ http_got_header(struct socket *socket, struct read_buffer *rb)
|
||||
unsigned char *d;
|
||||
struct uri *uri = conn->proxied_uri; /* Set to the real uri */
|
||||
struct http_version version = { 0, 9 };
|
||||
enum connection_state state = (conn->state != S_PROC ? S_GETH : S_PROC);
|
||||
struct connection_state state = (!is_in_state(conn->state, S_PROC)
|
||||
? connection_state(S_GETH)
|
||||
: connection_state(S_PROC));
|
||||
int a, h = 200;
|
||||
int cf;
|
||||
|
||||
@ -1467,7 +1471,7 @@ http_got_header(struct socket *socket, struct read_buffer *rb)
|
||||
conn->tries = -1;
|
||||
}
|
||||
}
|
||||
retry_connection(conn, S_CANT_READ);
|
||||
retry_connection(conn, connection_state(S_CANT_READ));
|
||||
return;
|
||||
}
|
||||
socket->state = SOCKET_RETRY_ONCLOSE;
|
||||
@ -1475,7 +1479,7 @@ http_got_header(struct socket *socket, struct read_buffer *rb)
|
||||
again:
|
||||
a = get_header(rb);
|
||||
if (a == -1) {
|
||||
abort_connection(conn, S_HTTP_ERROR);
|
||||
abort_connection(conn, connection_state(S_HTTP_ERROR));
|
||||
return;
|
||||
}
|
||||
if (!a) {
|
||||
@ -1488,7 +1492,7 @@ again:
|
||||
if (a == -2) a = 0;
|
||||
if ((a && get_http_code(rb, &h, &version))
|
||||
|| h == 101) {
|
||||
abort_connection(conn, S_HTTP_ERROR);
|
||||
abort_connection(conn, connection_state(S_HTTP_ERROR));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1501,13 +1505,13 @@ again:
|
||||
head = (a ? memacpy(rb->data, a)
|
||||
: stracpy("\r\nContent-Type: text/html\r\n"));
|
||||
if (!head) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
if (check_http_server_bugs(uri, http, head)) {
|
||||
mem_free(head);
|
||||
retry_connection(conn, S_RESTART);
|
||||
retry_connection(conn, connection_state(S_RESTART));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1526,7 +1530,7 @@ again:
|
||||
if (h2 >= 100 && h2 < 600) h = h2;
|
||||
if (h == 101) {
|
||||
mem_free(head);
|
||||
abort_connection(conn, S_HTTP_ERROR);
|
||||
abort_connection(conn, connection_state(S_HTTP_ERROR));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1544,23 +1548,23 @@ again:
|
||||
|
||||
if (h == 100) {
|
||||
mem_free(head);
|
||||
state = S_PROC;
|
||||
state = connection_state(S_PROC);
|
||||
kill_buffer_data(rb, a);
|
||||
goto again;
|
||||
}
|
||||
if (h < 200) {
|
||||
mem_free(head);
|
||||
abort_connection(conn, S_HTTP_ERROR);
|
||||
abort_connection(conn, connection_state(S_HTTP_ERROR));
|
||||
return;
|
||||
}
|
||||
if (h == 304) {
|
||||
mem_free(head);
|
||||
http_end_request(conn, S_OK, 1);
|
||||
http_end_request(conn, connection_state(S_OK), 1);
|
||||
return;
|
||||
}
|
||||
if (h == 204) {
|
||||
mem_free(head);
|
||||
http_end_request(conn, S_HTTP_204, 0);
|
||||
http_end_request(conn, connection_state(S_HTTP_204), 0);
|
||||
return;
|
||||
}
|
||||
if (h == 200 && connection_is_https_proxy(conn) && !conn->socket->ssl) {
|
||||
@ -1569,7 +1573,7 @@ again:
|
||||
socket->need_ssl = 1;
|
||||
complete_connect_socket(socket, uri, http_send_header);
|
||||
#else
|
||||
abort_connection(conn, S_SSL_ERROR);
|
||||
abort_connection(conn, connection_state(S_SSL_ERROR));
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
@ -1577,7 +1581,7 @@ again:
|
||||
conn->cached = get_cache_entry(conn->uri);
|
||||
if (!conn->cached) {
|
||||
mem_free(head);
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
conn->cached->cgi = conn->cgi;
|
||||
@ -1671,7 +1675,7 @@ again:
|
||||
if (h == 401) {
|
||||
if (check_http_authentication(conn, uri,
|
||||
conn->cached->head, "WWW-Authenticate")) {
|
||||
retry_connection(conn, S_RESTART);
|
||||
retry_connection(conn, connection_state(S_RESTART));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1744,7 +1748,7 @@ again:
|
||||
if ((conn->progress->start <= 0 && conn->from > cf) || conn->from < 0) {
|
||||
/* We don't want this if conn->progress.start because then conn->from will
|
||||
* be probably value of conn->progress.start, while cf is 0. */
|
||||
abort_connection(conn, S_HTTP_ERROR);
|
||||
abort_connection(conn, connection_state(S_HTTP_ERROR));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1811,7 +1815,7 @@ again:
|
||||
if (conn->from) {
|
||||
conn->from = 0;
|
||||
mem_free(d);
|
||||
retry_connection(conn, S_MODIFIED);
|
||||
retry_connection(conn, connection_state(S_MODIFIED));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1843,7 +1847,7 @@ again:
|
||||
if (conn->from) {
|
||||
conn->from = 0;
|
||||
mem_free(d);
|
||||
retry_connection(conn, S_MODIFIED);
|
||||
retry_connection(conn, connection_state(S_MODIFIED));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ init_nntp_connection_info(struct connection *conn)
|
||||
|
||||
nntp = mem_calloc(1, sizeof(*nntp));
|
||||
if (!nntp) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -143,7 +143,7 @@ init_nntp_connection_info(struct connection *conn)
|
||||
break;
|
||||
|
||||
/* FIXME: Special S_NNTP_BAD_RANGE */
|
||||
abort_connection(conn, S_BAD_URL);
|
||||
abort_connection(conn, connection_state(S_BAD_URL));
|
||||
return NULL;
|
||||
|
||||
case NNTP_TARGET_ARTICLE_NUMBER:
|
||||
@ -157,12 +157,12 @@ init_nntp_connection_info(struct connection *conn)
|
||||
/* Map nntp://<server>/<group> to nntp://<server>/<group>/ so
|
||||
* we get only one cache entry with content. */
|
||||
if (!groupend) {
|
||||
enum connection_state state = S_OK;
|
||||
struct connection_state state = connection_state(S_OK);
|
||||
|
||||
conn->cached = get_cache_entry(conn->uri);
|
||||
if (!conn->cached
|
||||
|| !redirect_cache(conn->cached, "/", 0, 0))
|
||||
state = S_OUT_OF_MEM;
|
||||
state = connection_state(S_OUT_OF_MEM);
|
||||
|
||||
abort_connection(conn, state);
|
||||
return NULL;
|
||||
@ -170,7 +170,7 @@ init_nntp_connection_info(struct connection *conn)
|
||||
|
||||
/* Reject nntp://<server>/<group>/<group> */
|
||||
if (nntp->group.source) {
|
||||
abort_connection(conn, S_BAD_URL);
|
||||
abort_connection(conn, connection_state(S_BAD_URL));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -196,7 +196,7 @@ nntp_quit(struct connection *conn)
|
||||
|
||||
info = mem_calloc(1, sizeof(*info));
|
||||
if (!info) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -208,7 +208,7 @@ nntp_quit(struct connection *conn)
|
||||
}
|
||||
|
||||
static void
|
||||
nntp_end_request(struct connection *conn, enum connection_state state)
|
||||
nntp_end_request(struct connection *conn, struct connection_state state)
|
||||
{
|
||||
struct nntp_connection_info *nntp = conn->info;
|
||||
|
||||
@ -217,11 +217,11 @@ nntp_end_request(struct connection *conn, enum connection_state state)
|
||||
return;
|
||||
}
|
||||
|
||||
if (state == S_OK) {
|
||||
if (is_in_state(state, S_OK)) {
|
||||
if (conn->cached) {
|
||||
normalize_cache_entry(conn->cached, conn->from);
|
||||
}
|
||||
} else if (state == S_OUT_OF_MEM) {
|
||||
} else if (is_in_state(state, S_OUT_OF_MEM)) {
|
||||
/* FIXME: Clear the socket buffers before ending so the one
|
||||
* grabing the keepalive connection will be able to go on. */
|
||||
}
|
||||
@ -239,38 +239,39 @@ read_nntp_data(struct socket *socket, struct read_buffer *rb)
|
||||
struct connection *conn = socket->conn;
|
||||
|
||||
if (socket->state == SOCKET_CLOSED) {
|
||||
nntp_end_request(conn, S_OK);
|
||||
nntp_end_request(conn, connection_state(S_OK));
|
||||
return;
|
||||
}
|
||||
|
||||
switch (read_nntp_response_data(conn, rb)) {
|
||||
switch (read_nntp_response_data(conn, rb).basic) {
|
||||
case S_OK:
|
||||
nntp_send_command(conn);
|
||||
break;
|
||||
|
||||
case S_OUT_OF_MEM:
|
||||
nntp_end_request(conn, S_OUT_OF_MEM);
|
||||
nntp_end_request(conn, connection_state(S_OUT_OF_MEM));
|
||||
break;
|
||||
|
||||
case S_TRANS:
|
||||
default:
|
||||
read_from_socket(conn->socket, rb, S_TRANS, read_nntp_data);
|
||||
read_from_socket(conn->socket, rb, connection_state(S_TRANS),
|
||||
read_nntp_data);
|
||||
}
|
||||
}
|
||||
|
||||
/* Translate NNTP code to the internal connection state. */
|
||||
static enum connection_state
|
||||
static struct connection_state
|
||||
get_nntp_connection_state(enum nntp_code code)
|
||||
{
|
||||
switch (code) {
|
||||
case NNTP_CODE_400_GOODBYE: return S_NNTP_SERVER_HANG_UP;
|
||||
case NNTP_CODE_411_GROUP_UNKNOWN: return S_NNTP_GROUP_UNKNOWN;
|
||||
case NNTP_CODE_423_ARTICLE_NONUMBER: return S_NNTP_ARTICLE_UNKNOWN;
|
||||
case NNTP_CODE_430_ARTICLE_NOID: return S_NNTP_ARTICLE_UNKNOWN;
|
||||
case NNTP_CODE_436_ARTICLE_TRANSFER: return S_NNTP_TRANSFER_ERROR;
|
||||
case NNTP_CODE_480_AUTH_REQUIRED: return S_NNTP_AUTH_REQUIRED;
|
||||
case NNTP_CODE_502_ACCESS_DENIED: return S_NNTP_ACCESS_DENIED;
|
||||
case NNTP_CODE_503_PROGRAM_FAULT: return S_NNTP_SERVER_ERROR;
|
||||
case NNTP_CODE_400_GOODBYE: return connection_state(S_NNTP_SERVER_HANG_UP);
|
||||
case NNTP_CODE_411_GROUP_UNKNOWN: return connection_state(S_NNTP_GROUP_UNKNOWN);
|
||||
case NNTP_CODE_423_ARTICLE_NONUMBER: return connection_state(S_NNTP_ARTICLE_UNKNOWN);
|
||||
case NNTP_CODE_430_ARTICLE_NOID: return connection_state(S_NNTP_ARTICLE_UNKNOWN);
|
||||
case NNTP_CODE_436_ARTICLE_TRANSFER: return connection_state(S_NNTP_TRANSFER_ERROR);
|
||||
case NNTP_CODE_480_AUTH_REQUIRED: return connection_state(S_NNTP_AUTH_REQUIRED);
|
||||
case NNTP_CODE_502_ACCESS_DENIED: return connection_state(S_NNTP_ACCESS_DENIED);
|
||||
case NNTP_CODE_503_PROGRAM_FAULT: return connection_state(S_NNTP_SERVER_ERROR);
|
||||
|
||||
case NNTP_CODE_412_GROUP_UNSET:
|
||||
case NNTP_CODE_420_ARTICLE_UNSET:
|
||||
@ -287,7 +288,7 @@ get_nntp_connection_state(enum nntp_code code)
|
||||
default:
|
||||
/* Notice and error codes for stuff which is either not
|
||||
* supported or which is not supposed to happen. */
|
||||
return S_NNTP_ERROR;
|
||||
return connection_state(S_NNTP_ERROR);
|
||||
};
|
||||
}
|
||||
|
||||
@ -298,7 +299,7 @@ nntp_got_response(struct socket *socket, struct read_buffer *rb)
|
||||
struct nntp_connection_info *nntp = conn->info;
|
||||
|
||||
if (socket->state == SOCKET_CLOSED) {
|
||||
nntp_end_request(conn, S_OK);
|
||||
nntp_end_request(conn, connection_state(S_OK));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -306,11 +307,12 @@ nntp_got_response(struct socket *socket, struct read_buffer *rb)
|
||||
|
||||
switch (nntp->code) {
|
||||
case NNTP_CODE_NONE:
|
||||
read_from_socket(conn->socket, rb, S_TRANS, nntp_got_response);
|
||||
read_from_socket(conn->socket, rb, connection_state(S_TRANS),
|
||||
nntp_got_response);
|
||||
break;
|
||||
|
||||
case NNTP_CODE_INVALID:
|
||||
nntp_end_request(conn, S_NNTP_ERROR);
|
||||
nntp_end_request(conn, connection_state(S_NNTP_ERROR));
|
||||
break;
|
||||
|
||||
case NNTP_CODE_200_HELLO:
|
||||
@ -320,7 +322,7 @@ nntp_got_response(struct socket *socket, struct read_buffer *rb)
|
||||
break;
|
||||
|
||||
case NNTP_CODE_205_GOODBYE:
|
||||
nntp_end_request(conn, S_OK);
|
||||
nntp_end_request(conn, connection_state(S_OK));
|
||||
break;
|
||||
|
||||
case NNTP_CODE_215_FOLLOW_GROUPS:
|
||||
@ -509,19 +511,20 @@ nntp_send_command(struct connection *conn)
|
||||
nntp->command = get_nntp_command(nntp);
|
||||
|
||||
if (nntp->command == NNTP_COMMAND_NONE) {
|
||||
nntp_end_request(conn, S_OK);
|
||||
nntp_end_request(conn, connection_state(S_OK));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!init_string(&req)) {
|
||||
nntp_end_request(conn, S_OUT_OF_MEM);
|
||||
nntp_end_request(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
/* FIXME: Check non empty and < NNTP_MAX_COMMAND_LENGTH */
|
||||
add_nntp_command_to_string(&req, nntp);
|
||||
|
||||
request_from_socket(conn->socket, req.source, req.length, S_SENT,
|
||||
request_from_socket(conn->socket, req.source, req.length,
|
||||
connection_state(S_SENT),
|
||||
SOCKET_END_ONCLOSE, nntp_got_response);
|
||||
done_string(&req);
|
||||
}
|
||||
@ -567,13 +570,13 @@ news_protocol_handler(struct connection *conn)
|
||||
|
||||
if (!*server) server = getenv("NNTPSERVER");
|
||||
if (!server || !*server) {
|
||||
abort_connection(conn, S_NNTP_NEWS_SERVER);
|
||||
abort_connection(conn, connection_state(S_NNTP_NEWS_SERVER));
|
||||
return;
|
||||
}
|
||||
|
||||
conn->cached = get_cache_entry(conn->uri);
|
||||
if (!conn->cached || !init_string(&location)) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -586,5 +589,5 @@ news_protocol_handler(struct connection *conn)
|
||||
|
||||
done_string(&location);
|
||||
|
||||
abort_connection(conn, S_OK);
|
||||
abort_connection(conn, connection_state(S_OK));
|
||||
}
|
||||
|
@ -89,14 +89,14 @@ get_nntp_message_header_end(unsigned char *data, int datalen)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static enum connection_state
|
||||
static struct connection_state
|
||||
init_nntp_header(struct connection *conn, struct read_buffer *rb)
|
||||
{
|
||||
struct nntp_connection_info *nntp = conn->info;
|
||||
|
||||
if (!conn->cached) {
|
||||
conn->cached = get_cache_entry(conn->uri);
|
||||
if (!conn->cached) return S_OUT_OF_MEM;
|
||||
if (!conn->cached) return connection_state(S_OUT_OF_MEM);
|
||||
|
||||
} else if (conn->cached->head || conn->cached->content_type) {
|
||||
/* If the head is set wipe out the content to be sure */
|
||||
@ -107,7 +107,7 @@ init_nntp_header(struct connection *conn, struct read_buffer *rb)
|
||||
/* XXX: Override any Content-Type line in the header */
|
||||
mem_free_set(&conn->cached->content_type, stracpy("text/html"));
|
||||
if (!conn->cached->content_type)
|
||||
return S_OUT_OF_MEM;
|
||||
return connection_state(S_OUT_OF_MEM);
|
||||
|
||||
switch (nntp->target) {
|
||||
case NNTP_TARGET_ARTICLE_NUMBER:
|
||||
@ -119,12 +119,12 @@ init_nntp_header(struct connection *conn, struct read_buffer *rb)
|
||||
end = get_nntp_message_header_end(rb->data, rb->length);
|
||||
if (!end) {
|
||||
/* Redo the whole cache entry thing next time */
|
||||
return S_TRANS;
|
||||
return connection_state(S_TRANS);
|
||||
}
|
||||
|
||||
/* FIXME: Add the NNTP response code line */
|
||||
conn->cached->head = stracpy("FIXME NNTP response code\r\n");
|
||||
if (!conn->cached->head) return S_OUT_OF_MEM;
|
||||
if (!conn->cached->head) return connection_state(S_OUT_OF_MEM);
|
||||
|
||||
add_to_strn(&conn->cached->head, rb->data);
|
||||
|
||||
@ -140,7 +140,7 @@ init_nntp_header(struct connection *conn, struct read_buffer *rb)
|
||||
break;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
return connection_state(S_OK);
|
||||
}
|
||||
|
||||
|
||||
@ -462,31 +462,31 @@ add_nntp_html_line(struct string *html, struct connection *conn,
|
||||
add_char_to_string(html, '\n');
|
||||
}
|
||||
|
||||
enum connection_state
|
||||
struct connection_state
|
||||
read_nntp_response_data(struct connection *conn, struct read_buffer *rb)
|
||||
{
|
||||
struct string html;
|
||||
unsigned char *end;
|
||||
enum connection_state state = S_TRANS;
|
||||
struct connection_state state = connection_state(S_TRANS);
|
||||
|
||||
if (conn->from == 0) {
|
||||
switch (init_nntp_header(conn, rb)) {
|
||||
switch (init_nntp_header(conn, rb).basic) {
|
||||
case S_OK:
|
||||
break;
|
||||
|
||||
case S_OUT_OF_MEM:
|
||||
return S_OUT_OF_MEM;
|
||||
return connection_state(S_OUT_OF_MEM);
|
||||
|
||||
case S_TRANS:
|
||||
return S_TRANS;
|
||||
return connection_state(S_TRANS);
|
||||
|
||||
default:
|
||||
return S_NNTP_ERROR;
|
||||
return connection_state(S_NNTP_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
if (!init_string(&html))
|
||||
return S_OUT_OF_MEM;
|
||||
return connection_state(S_OUT_OF_MEM);
|
||||
|
||||
if (conn->from == 0)
|
||||
add_nntp_html_start(&html, conn);
|
||||
@ -495,7 +495,7 @@ read_nntp_response_data(struct connection *conn, struct read_buffer *rb)
|
||||
unsigned char *line = check_nntp_line(rb->data, end);
|
||||
|
||||
if (!line) {
|
||||
state = S_OK;
|
||||
state = connection_state(S_OK);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -505,7 +505,7 @@ read_nntp_response_data(struct connection *conn, struct read_buffer *rb)
|
||||
kill_buffer_data(rb, end - rb->data);
|
||||
}
|
||||
|
||||
if (state != S_TRANS)
|
||||
if (!is_in_state(state, S_TRANS))
|
||||
add_nntp_html_end(&html, conn);
|
||||
|
||||
add_fragment(conn->cached, conn->from, html.source, html.length);
|
||||
|
@ -13,7 +13,7 @@ struct read_buffer;
|
||||
* S_TRANS (transferring) means 'end-of-text' not reached yet
|
||||
* S_OK means no more text expected
|
||||
* S_OUT_OF_MEM allocation failure of some sort */
|
||||
enum connection_state
|
||||
struct connection_state
|
||||
read_nntp_response_data(struct connection *conn, struct read_buffer *rb);
|
||||
|
||||
/* Reads the first line in the NNTP response from the @rb read buffer and
|
||||
|
@ -212,7 +212,7 @@ static void
|
||||
generic_external_protocol_handler(struct session *ses, struct uri *uri)
|
||||
{
|
||||
/* [gettext_accelerator_context(generic_external_protocol_handler)] */
|
||||
enum connection_state state;
|
||||
struct connection_state state;
|
||||
|
||||
switch (uri->protocol) {
|
||||
case PROTOCOL_JAVASCRIPT:
|
||||
@ -220,18 +220,18 @@ generic_external_protocol_handler(struct session *ses, struct uri *uri)
|
||||
ecmascript_protocol_handler(ses, uri);
|
||||
return;
|
||||
#else
|
||||
state = S_NO_JAVASCRIPT;
|
||||
state = connection_state(S_NO_JAVASCRIPT);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case PROTOCOL_UNKNOWN:
|
||||
state = S_UNKNOWN_PROTOCOL;
|
||||
state = connection_state(S_UNKNOWN_PROTOCOL);
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifndef CONFIG_SSL
|
||||
if (get_protocol_need_ssl(uri->protocol)) {
|
||||
state = S_SSL_ERROR;
|
||||
state = connection_state(S_SSL_ERROR);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
@ -55,7 +55,7 @@ proxy_probe_no_proxy(unsigned char *url, unsigned char *no_proxy)
|
||||
|
||||
static struct uri *
|
||||
proxy_uri(struct uri *uri, unsigned char *proxy,
|
||||
enum connection_state *connection_state)
|
||||
struct connection_state *error_state)
|
||||
{
|
||||
struct string string;
|
||||
|
||||
@ -70,10 +70,10 @@ proxy_uri(struct uri *uri, unsigned char *proxy,
|
||||
/* XXX: Assume the problem is due to @proxy having bad format.
|
||||
* This is a lot faster easier than checking the format. */
|
||||
if (!uri)
|
||||
*connection_state = S_PROXY_ERROR;
|
||||
*error_state = connection_state(S_PROXY_ERROR);
|
||||
} else {
|
||||
uri = NULL;
|
||||
*connection_state = S_OUT_OF_MEM;
|
||||
*error_state = connection_state(S_OUT_OF_MEM);
|
||||
}
|
||||
|
||||
done_string(&string);
|
||||
@ -118,7 +118,7 @@ get_protocol_proxy(unsigned char *opt,
|
||||
|
||||
static struct uri *
|
||||
get_proxy_worker(struct uri *uri, unsigned char *proxy,
|
||||
enum connection_state *connection_state)
|
||||
struct connection_state *error_state)
|
||||
{
|
||||
unsigned char *protocol_proxy = NULL;
|
||||
|
||||
@ -126,7 +126,7 @@ get_proxy_worker(struct uri *uri, unsigned char *proxy,
|
||||
if (*proxy) {
|
||||
proxy = strip_proxy_protocol(proxy, "http://", "ftp://");
|
||||
|
||||
return proxy_uri(uri, proxy, connection_state);
|
||||
return proxy_uri(uri, proxy, error_state);
|
||||
}
|
||||
|
||||
/* "" from script_hook_get_proxy() */
|
||||
@ -177,14 +177,14 @@ get_proxy_worker(struct uri *uri, unsigned char *proxy,
|
||||
if (!no_proxy || !*no_proxy) no_proxy = getenv("no_proxy");
|
||||
|
||||
if (!proxy_probe_no_proxy(uri->host, no_proxy))
|
||||
return proxy_uri(uri, protocol_proxy, connection_state);
|
||||
return proxy_uri(uri, protocol_proxy, error_state);
|
||||
}
|
||||
|
||||
return get_composed_uri(uri, URI_BASE);
|
||||
}
|
||||
|
||||
struct uri *
|
||||
get_proxy_uri(struct uri *uri, enum connection_state *connection_state)
|
||||
get_proxy_uri(struct uri *uri, struct connection_state *error_state)
|
||||
{
|
||||
if (uri->protocol == PROTOCOL_PROXY) {
|
||||
return get_composed_uri(uri, URI_BASE);
|
||||
@ -196,11 +196,11 @@ get_proxy_uri(struct uri *uri, enum connection_state *connection_state)
|
||||
set_event_id(get_proxy_event_id, "get-proxy");
|
||||
trigger_event(get_proxy_event_id, &tmp, struri(uri));
|
||||
|
||||
uri = get_proxy_worker(uri, tmp, connection_state);
|
||||
uri = get_proxy_worker(uri, tmp, error_state);
|
||||
mem_free_if(tmp);
|
||||
return uri;
|
||||
#else
|
||||
return get_proxy_worker(uri, NULL, connection_state);
|
||||
return get_proxy_worker(uri, NULL, error_state);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,14 @@
|
||||
#ifndef EL__PROTOCOL_PROXY_H
|
||||
#define EL__PROTOCOL_PROXY_H
|
||||
|
||||
enum connection_state;
|
||||
struct connection_state;
|
||||
struct uri;
|
||||
|
||||
/* Checks if the passed URI has been configured to go through a proxy. The
|
||||
* fragment is removed from the returned URI. */
|
||||
/* If @connection_state is non-NULL it will be set to indicate what error
|
||||
* occurred if the function returns NULL. */
|
||||
struct uri *get_proxy_uri(struct uri *uri, enum connection_state *connection_state);
|
||||
struct uri *get_proxy_uri(struct uri *uri, struct connection_state *connection_state);
|
||||
|
||||
/* ``Translates'' the passed URI into the URI being proxied. If it is not a
|
||||
* proxy:// URI it will return the URI with the fragment removed. */
|
||||
|
@ -71,10 +71,13 @@ static FILE *header_out, *data_out;
|
||||
* process, and it would be very cumbersome to free those. */
|
||||
|
||||
static void
|
||||
smb_error(int error)
|
||||
smb_error(struct connection_state error)
|
||||
{
|
||||
if (is_system_error(error))
|
||||
fprintf(data_out, "S%d\n", (int) error.syserr);
|
||||
else
|
||||
fprintf(data_out, "I%d\n", (int) error.basic);
|
||||
fputs("text/x-error", header_out);
|
||||
fprintf(data_out, "%d\n", error);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -252,8 +255,8 @@ smb_directory(int dir, struct uri *uri)
|
||||
struct string buf;
|
||||
unsigned char dircolor[8] = "";
|
||||
|
||||
if (init_directory_listing(&buf, uri) != S_OK) {
|
||||
smb_error(-S_OUT_OF_MEM);
|
||||
if (!is_in_state(init_directory_listing(&buf, uri), S_OK)) {
|
||||
smb_error(connection_state(S_OUT_OF_MEM));
|
||||
}
|
||||
|
||||
fputs("text/html", header_out);
|
||||
@ -297,7 +300,7 @@ do_smb(struct connection *conn)
|
||||
unsigned char *uri_string = get_uri_string(uri, URI_HOST | URI_PORT | URI_DATA);
|
||||
|
||||
if (!uri_string || !init_string(&string)) {
|
||||
smb_error(-S_OUT_OF_MEM);
|
||||
smb_error(connection_state(S_OUT_OF_MEM));
|
||||
}
|
||||
/* Must URI-encode the username and password to avoid
|
||||
* ambiguity if they contain "/:@" characters.
|
||||
@ -320,10 +323,10 @@ do_smb(struct connection *conn)
|
||||
}
|
||||
|
||||
if (!url) {
|
||||
smb_error(-S_OUT_OF_MEM);
|
||||
smb_error(connection_state(S_OUT_OF_MEM));
|
||||
}
|
||||
if (smbc_init(smb_auth, 0)) {
|
||||
smb_error(errno);
|
||||
smb_error(connection_state_for_errno(errno));
|
||||
};
|
||||
|
||||
dir = smbc_opendir(url);
|
||||
@ -345,12 +348,12 @@ do_smb(struct connection *conn)
|
||||
* for credentials. */
|
||||
if (errno == ENOENT && errno_from_opendir == EACCES)
|
||||
errno = errno_from_opendir;
|
||||
smb_error(errno);
|
||||
smb_error(connection_state_for_errno(errno));
|
||||
}
|
||||
|
||||
res = smbc_fstat(file, &sb);
|
||||
if (res) {
|
||||
smb_error(res);
|
||||
smb_error(connection_state_for_errno(res));
|
||||
}
|
||||
/* filesize */
|
||||
fprintf(header_out, "%" OFF_PRINT_FORMAT,
|
||||
@ -375,7 +378,7 @@ static void
|
||||
prompt_username_pw(struct connection *conn)
|
||||
{
|
||||
add_auth_entry(conn->uri, "Samba", NULL, NULL, 0);
|
||||
abort_connection(conn, S_OK);
|
||||
abort_connection(conn, connection_state(S_OK));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -383,10 +386,10 @@ smb_got_error(struct socket *socket, struct read_buffer *rb)
|
||||
{
|
||||
int len = rb->length;
|
||||
struct connection *conn = socket->conn;
|
||||
int error;
|
||||
struct connection_state error;
|
||||
|
||||
if (len < 0) {
|
||||
abort_connection(conn, -errno);
|
||||
abort_connection(conn, connection_state_for_errno(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -396,20 +399,28 @@ smb_got_error(struct socket *socket, struct read_buffer *rb)
|
||||
* pipe. */
|
||||
assert(rb->freespace >= 1);
|
||||
if_assert_failed {
|
||||
abort_connection(conn, S_INTERNAL);
|
||||
abort_connection(conn, connection_state(S_INTERNAL));
|
||||
return;
|
||||
}
|
||||
rb->data[len] = '\0';
|
||||
error = atoi(rb->data);
|
||||
kill_buffer_data(rb, len);
|
||||
switch (error) {
|
||||
case EACCES:
|
||||
prompt_username_pw(conn);
|
||||
switch (rb->data[0]) {
|
||||
case 'S':
|
||||
error = connection_state_for_errno(atoi(rb->data + 1));
|
||||
break;
|
||||
case 'I':
|
||||
error = connection_state(atoi(rb->data + 1));
|
||||
break;
|
||||
default:
|
||||
abort_connection(conn, -error);
|
||||
ERROR("malformed error code: %s", rb->data);
|
||||
error = connection_state(S_INTERNAL);
|
||||
break;
|
||||
}
|
||||
kill_buffer_data(rb, len);
|
||||
|
||||
if (is_system_error(error) && error.syserr == EACCES)
|
||||
prompt_username_pw(conn);
|
||||
else
|
||||
abort_connection(conn, error);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -419,12 +430,12 @@ smb_got_data(struct socket *socket, struct read_buffer *rb)
|
||||
struct connection *conn = socket->conn;
|
||||
|
||||
if (len < 0) {
|
||||
abort_connection(conn, -errno);
|
||||
abort_connection(conn, connection_state_for_errno(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!len) {
|
||||
abort_connection(conn, S_OK);
|
||||
abort_connection(conn, connection_state(S_OK));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -435,7 +446,7 @@ smb_got_data(struct socket *socket, struct read_buffer *rb)
|
||||
conn->from += len;
|
||||
kill_buffer_data(rb, len);
|
||||
|
||||
read_from_socket(socket, rb, S_TRANS, smb_got_data);
|
||||
read_from_socket(socket, rb, connection_state(S_TRANS), smb_got_data);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -454,7 +465,7 @@ smb_got_header(struct socket *socket, struct read_buffer *rb)
|
||||
* and assume abort_connection will do them?) */
|
||||
close_socket(socket);
|
||||
close_socket(conn->data_socket);
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
socket->state = SOCKET_END_ONCLOSE;
|
||||
@ -477,7 +488,7 @@ smb_got_header(struct socket *socket, struct read_buffer *rb)
|
||||
|
||||
/* avoid error */
|
||||
if (!conn->est_length) {
|
||||
abort_connection(conn, S_OK);
|
||||
abort_connection(conn, connection_state(S_OK));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -492,14 +503,16 @@ smb_got_header(struct socket *socket, struct read_buffer *rb)
|
||||
if (!buf) {
|
||||
close_socket(socket);
|
||||
close_socket(conn->data_socket);
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
if (error) {
|
||||
mem_free_set(&conn->cached->content_type, stracpy("text/html"));
|
||||
read_from_socket(conn->data_socket, buf, S_CONN, smb_got_error);
|
||||
read_from_socket(conn->data_socket, buf,
|
||||
connection_state(S_CONN), smb_got_error);
|
||||
} else {
|
||||
read_from_socket(conn->data_socket, buf, S_CONN, smb_got_data);
|
||||
read_from_socket(conn->data_socket, buf,
|
||||
connection_state(S_CONN), smb_got_data);
|
||||
}
|
||||
}
|
||||
|
||||
@ -535,7 +548,7 @@ smb_protocol_handler(struct connection *conn)
|
||||
if (smb_pipe[1] >= 0) close(smb_pipe[1]);
|
||||
if (header_pipe[0] >= 0) close(header_pipe[0]);
|
||||
if (header_pipe[1] >= 0) close(header_pipe[1]);
|
||||
abort_connection(conn, -s_errno);
|
||||
abort_connection(conn, connection_state_for_errno(s_errno));
|
||||
return;
|
||||
}
|
||||
conn->from = 0;
|
||||
@ -550,7 +563,7 @@ smb_protocol_handler(struct connection *conn)
|
||||
close(smb_pipe[1]);
|
||||
close(header_pipe[0]);
|
||||
close(header_pipe[1]);
|
||||
retry_connection(conn, -s_errno);
|
||||
retry_connection(conn, connection_state_for_errno(s_errno));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -594,9 +607,10 @@ smb_protocol_handler(struct connection *conn)
|
||||
if (!buf2) {
|
||||
close_socket(conn->data_socket);
|
||||
close_socket(conn->socket);
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
read_from_socket(conn->socket, buf2, S_CONN, smb_got_header);
|
||||
read_from_socket(conn->socket, buf2,
|
||||
connection_state(S_CONN), smb_got_header);
|
||||
}
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ get_user_program(struct terminal *term, unsigned char *progid, int progidlen)
|
||||
|
||||
/* declared in "session/session.h" */
|
||||
void
|
||||
print_error_dialog(struct session *ses, enum connection_state state,
|
||||
print_error_dialog(struct session *ses, struct connection_state state,
|
||||
struct uri *uri, enum connection_priority priority)
|
||||
{
|
||||
stub_called("print_error_dialog");
|
||||
|
@ -68,7 +68,7 @@ int
|
||||
download_is_progressing(struct download *download)
|
||||
{
|
||||
return download
|
||||
&& download->state == S_TRANS
|
||||
&& is_in_state(download->state, S_TRANS)
|
||||
&& has_progress(download->progress);
|
||||
}
|
||||
|
||||
@ -318,9 +318,9 @@ download_data_store(struct download *download, struct file_download *file_downlo
|
||||
return;
|
||||
}
|
||||
|
||||
if (download->state != S_OK) {
|
||||
if (!is_in_state(download->state, S_OK)) {
|
||||
unsigned char *url = get_uri_string(file_download->uri, URI_PUBLIC);
|
||||
enum connection_state state = download->state;
|
||||
struct connection_state state = download->state;
|
||||
|
||||
abort_download_and_beep(file_download, term);
|
||||
|
||||
@ -397,7 +397,7 @@ download_data(struct download *download, struct file_download *file_download)
|
||||
done_uri(file_download->uri);
|
||||
|
||||
file_download->uri = get_uri_reference(cached->redirect);
|
||||
file_download->download.state = S_WAIT_REDIR;
|
||||
file_download->download.state = connection_state(S_WAIT_REDIR);
|
||||
|
||||
if (file_download->dlg_data)
|
||||
redraw_dialog(file_download->dlg_data, 1);
|
||||
@ -955,7 +955,7 @@ init_type_query(struct session *ses, struct download *download,
|
||||
object_lock(type_query->cached);
|
||||
|
||||
move_download(download, &type_query->download, PRI_MAIN);
|
||||
download->state = S_OK;
|
||||
download->state = connection_state(S_OK);
|
||||
|
||||
add_to_list(ses->type_queries, type_query);
|
||||
|
||||
|
@ -34,8 +34,8 @@ struct download {
|
||||
void *data;
|
||||
struct progress *progress;
|
||||
|
||||
enum connection_state state;
|
||||
enum connection_state prev_error;
|
||||
struct connection_state state;
|
||||
struct connection_state prev_error;
|
||||
enum connection_priority pri;
|
||||
};
|
||||
|
||||
|
@ -241,7 +241,7 @@ get_current_download(struct session *ses)
|
||||
else if (have_location(ses))
|
||||
download = &cur_loc(ses)->download;
|
||||
|
||||
if (download && download->state == S_OK) {
|
||||
if (download && is_in_state(download->state, S_OK)) {
|
||||
struct file_to_load *ftl;
|
||||
|
||||
foreach (ftl, ses->more_files)
|
||||
@ -255,7 +255,7 @@ get_current_download(struct session *ses)
|
||||
}
|
||||
|
||||
void
|
||||
print_error_dialog(struct session *ses, enum connection_state state,
|
||||
print_error_dialog(struct session *ses, struct connection_state state,
|
||||
struct uri *uri, enum connection_priority priority)
|
||||
{
|
||||
struct string msg;
|
||||
@ -602,7 +602,7 @@ doc_loading_callback(struct download *download, struct session *ses)
|
||||
|
||||
start_document_refreshes(ses);
|
||||
|
||||
if (download->state != S_OK) {
|
||||
if (!is_in_state(download->state, S_OK)) {
|
||||
print_error_dialog(ses, download->state,
|
||||
ses->doc_view->document->uri,
|
||||
download->pri);
|
||||
@ -1116,7 +1116,8 @@ decode_session_info(struct terminal *term, struct terminal_info *info)
|
||||
/* End loop if initialization fails */
|
||||
len = 0;
|
||||
} else if (bad_url) {
|
||||
print_error_dialog(ses, S_BAD_URL, NULL, PRI_MAIN);
|
||||
print_error_dialog(ses, connection_state(S_BAD_URL),
|
||||
NULL, PRI_MAIN);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -226,7 +226,7 @@ have_location(struct session *ses) {
|
||||
void set_session_referrer(struct session *ses, struct uri *referrer);
|
||||
|
||||
void
|
||||
print_error_dialog(struct session *ses, enum connection_state state,
|
||||
print_error_dialog(struct session *ses, struct connection_state state,
|
||||
struct uri *uri, enum connection_priority priority);
|
||||
|
||||
void process_file_requests(struct session *);
|
||||
|
@ -543,7 +543,8 @@ loading_callback(struct download *download, struct session *ses)
|
||||
if (d == DO_MOVE_DISPLAY) doc_loading_callback(download, ses);
|
||||
}
|
||||
|
||||
if (is_in_result_state(download->state) && download->state != S_OK) {
|
||||
if (is_in_result_state(download->state)
|
||||
&& !is_in_state(download->state, S_OK)) {
|
||||
print_error_dialog(ses, download->state,
|
||||
download->conn ? download->conn->uri : NULL,
|
||||
download->pri);
|
||||
@ -564,7 +565,7 @@ do_follow_url(struct session *ses, struct uri *uri, unsigned char *target,
|
||||
protocol_external_handler_T *external_handler;
|
||||
|
||||
if (!uri) {
|
||||
print_error_dialog(ses, S_BAD_URL, uri, PRI_CANCEL);
|
||||
print_error_dialog(ses, connection_state(S_BAD_URL), uri, PRI_CANCEL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -263,7 +263,7 @@ dump_loading_callback(struct download *download, void *p)
|
||||
|
||||
}
|
||||
|
||||
if (download->state != S_OK) {
|
||||
if (!is_in_state(download->state, S_OK)) {
|
||||
usrerror(get_state_message(download->state, NULL));
|
||||
program.retval = RET_ERROR;
|
||||
goto terminate;
|
||||
|
Loading…
Reference in New Issue
Block a user