1
0
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:
Kalle Olavi Niemitalo 2008-08-03 15:24:26 +03:00 committed by Kalle Olavi Niemitalo
parent 40715ffbd4
commit 6c2e8cd7b2
49 changed files with 628 additions and 512 deletions

1
NEWS
View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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++;

View File

@ -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 {

View File

@ -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

View File

@ -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));
}
}

View File

@ -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,

View File

@ -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;

View File

@ -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. */

View File

@ -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;
}

View File

@ -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);

View File

@ -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

View File

@ -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));
}

View File

@ -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;

View File

@ -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

View File

@ -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;
}

View File

@ -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,

View File

@ -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;

View File

@ -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);

View File

@ -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,21 +75,25 @@ check_bittorrent_peer_blacklisting(struct bittorrent_peer_connection *peer,
|| !get_opt_bool("protocol.http.bugs.allow_blacklist"))
return;
switch (state) {
case -ECONNREFUSED:
case -ENETUNREACH:
flags |= BITTORRENT_BLACKLIST_PEER_POOL;
break;
case S_CANT_WRITE:
case S_CANT_READ:
if (!peer->local.handshake
|| !peer->remote.handshake)
if (is_system_error(state)) {
switch (state.syserr) {
case ECONNREFUSED:
case ENETUNREACH:
flags |= BITTORRENT_BLACKLIST_PEER_POOL;
break;
break;
}
} else {
switch (state.basic) {
case S_CANT_WRITE:
case S_CANT_READ:
if (!peer->local.handshake
|| !peer->remote.handshake)
flags |= BITTORRENT_BLACKLIST_PEER_POOL;
break;
default:
break;
default:
break;
}
}
if (flags != BITTORRENT_BLACKLIST_NONE) {
@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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

View File

@ -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));
}

View File

@ -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 */

View File

@ -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);

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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:

View File

@ -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;
}
}

View File

@ -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));
}

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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
}
}

View File

@ -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. */

View File

@ -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);
}
}

View File

@ -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");

View File

@ -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);

View File

@ -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;
};

View File

@ -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);
}
}

View File

@ -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 *);

View File

@ -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;
}

View File

@ -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;