HTTP seek support. Various bugfixes.
This commit is contained in:
parent
aa6b91afe9
commit
4f71e077b9
5 changed files with 231 additions and 83 deletions
|
@ -42,7 +42,11 @@ typedef struct http_data
|
||||||
grub_size_t current_line_len;
|
grub_size_t current_line_len;
|
||||||
int headers_recv;
|
int headers_recv;
|
||||||
int first_line_recv;
|
int first_line_recv;
|
||||||
|
int size_recv;
|
||||||
grub_net_tcp_socket_t sock;
|
grub_net_tcp_socket_t sock;
|
||||||
|
char *filename;
|
||||||
|
grub_err_t err;
|
||||||
|
char *errmsg;
|
||||||
} *http_data_t;
|
} *http_data_t;
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
|
@ -72,19 +76,25 @@ parse_line (http_data_t data, char *ptr, grub_size_t len)
|
||||||
{
|
{
|
||||||
case 200:
|
case 200:
|
||||||
break;
|
break;
|
||||||
|
case 404:
|
||||||
|
data->err = GRUB_ERR_FILE_NOT_FOUND;
|
||||||
|
data->errmsg = grub_xasprintf ("file `%s' not found", data->filename);
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
default:
|
default:
|
||||||
return grub_error (GRUB_ERR_NET_UNKNOWN_ERROR,
|
data->err = GRUB_ERR_NET_UNKNOWN_ERROR;
|
||||||
"unsupported HTTP error %d: %s",
|
data->errmsg = grub_xasprintf ("unsupported HTTP error %d: %s",
|
||||||
code, ptr);
|
code, ptr);
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
data->first_line_recv = 1;
|
data->first_line_recv = 1;
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
if (grub_memcmp (ptr, "Content-Length: ", sizeof ("Content-Length: ") - 1)
|
if (grub_memcmp (ptr, "Content-Length: ", sizeof ("Content-Length: ") - 1)
|
||||||
== 0)
|
== 0 && !data->size_recv)
|
||||||
{
|
{
|
||||||
ptr += sizeof ("Content-Length: ") - 1;
|
ptr += sizeof ("Content-Length: ") - 1;
|
||||||
data->file_size = grub_strtoull (ptr, &ptr, 10);
|
data->file_size = grub_strtoull (ptr, &ptr, 10);
|
||||||
|
data->size_recv = 1;
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
|
@ -98,10 +108,10 @@ http_err (grub_net_tcp_socket_t sock __attribute__ ((unused)),
|
||||||
http_data_t data = file->data;
|
http_data_t data = file->data;
|
||||||
|
|
||||||
if (data->sock)
|
if (data->sock)
|
||||||
grub_net_tcp_close (data->sock);
|
grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT);
|
||||||
grub_free (data);
|
|
||||||
if (data->current_line)
|
if (data->current_line)
|
||||||
grub_free (data->current_line);
|
grub_free (data->current_line);
|
||||||
|
grub_free (data);
|
||||||
file->device->net->eof = 1;
|
file->device->net->eof = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,7 +142,7 @@ http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)),
|
||||||
if (!t)
|
if (!t)
|
||||||
{
|
{
|
||||||
grub_netbuff_free (nb);
|
grub_netbuff_free (nb);
|
||||||
grub_net_tcp_close (data->sock);
|
grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT);
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,7 +161,7 @@ http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)),
|
||||||
data->current_line_len = 0;
|
data->current_line_len = 0;
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
grub_net_tcp_close (data->sock);
|
grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT);
|
||||||
grub_netbuff_free (nb);
|
grub_netbuff_free (nb);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -167,7 +177,7 @@ http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)),
|
||||||
if (!data->current_line)
|
if (!data->current_line)
|
||||||
{
|
{
|
||||||
grub_netbuff_free (nb);
|
grub_netbuff_free (nb);
|
||||||
grub_net_tcp_close (data->sock);
|
grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT);
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
}
|
}
|
||||||
data->current_line_len = (char *) nb->tail - ptr;
|
data->current_line_len = (char *) nb->tail - ptr;
|
||||||
|
@ -178,7 +188,7 @@ http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)),
|
||||||
err = parse_line (data, ptr, ptr2 - ptr);
|
err = parse_line (data, ptr, ptr2 - ptr);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
grub_net_tcp_close (data->sock);
|
grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT);
|
||||||
grub_netbuff_free (nb);
|
grub_netbuff_free (nb);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -191,7 +201,7 @@ http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)),
|
||||||
err = grub_netbuff_pull (nb, ptr - (char *) nb->data);
|
err = grub_netbuff_pull (nb, ptr - (char *) nb->data);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
grub_net_tcp_close (data->sock);
|
grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT);
|
||||||
grub_netbuff_free (nb);
|
grub_netbuff_free (nb);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -203,57 +213,51 @@ http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)),
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
http_open (struct grub_file *file, const char *filename)
|
http_establish (struct grub_file *file, grub_off_t offset, int initial)
|
||||||
{
|
{
|
||||||
struct grub_net_buff *nb;
|
http_data_t data = file->data;
|
||||||
http_data_t data;
|
|
||||||
grub_err_t err;
|
|
||||||
grub_uint8_t *ptr;
|
grub_uint8_t *ptr;
|
||||||
int i;
|
int i;
|
||||||
|
struct grub_net_buff *nb;
|
||||||
data = grub_zalloc (sizeof (*data));
|
grub_err_t err;
|
||||||
if (!data)
|
|
||||||
return grub_errno;
|
|
||||||
|
|
||||||
nb = grub_netbuff_alloc (GRUB_NET_TCP_RESERVE_SIZE
|
nb = grub_netbuff_alloc (GRUB_NET_TCP_RESERVE_SIZE
|
||||||
+ sizeof ("GET ") - 1
|
+ sizeof ("GET ") - 1
|
||||||
+ grub_strlen (filename)
|
+ grub_strlen (data->filename)
|
||||||
+ sizeof (" HTTP/1.1\r\nHost: ") - 1
|
+ sizeof (" HTTP/1.1\r\nHost: ") - 1
|
||||||
+ grub_strlen (file->device->net->server)
|
+ grub_strlen (file->device->net->server)
|
||||||
+ sizeof ("\r\nUser-Agent: " PACKAGE_STRING
|
+ sizeof ("\r\nUser-Agent: " PACKAGE_STRING
|
||||||
"\r\n\r\n") - 1);
|
"\r\n") - 1
|
||||||
|
+ sizeof ("Content-Range: bytes XXXXXXXXXXXXXXXXXXXX"
|
||||||
|
"-XXXXXXXXXXXXXXXXXXXX/"
|
||||||
|
"XXXXXXXXXXXXXXXXXXXX\r\n\r\n"));
|
||||||
if (!nb)
|
if (!nb)
|
||||||
{
|
return grub_errno;
|
||||||
grub_free (data);
|
|
||||||
return grub_errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
grub_netbuff_reserve (nb, GRUB_NET_TCP_RESERVE_SIZE);
|
grub_netbuff_reserve (nb, GRUB_NET_TCP_RESERVE_SIZE);
|
||||||
ptr = nb->tail;
|
ptr = nb->tail;
|
||||||
err = grub_netbuff_put (nb, sizeof ("GET ") - 1);
|
err = grub_netbuff_put (nb, sizeof ("GET ") - 1);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
grub_free (data);
|
|
||||||
grub_netbuff_free (nb);
|
grub_netbuff_free (nb);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
grub_memcpy (ptr, "GET ", sizeof ("GET ") - 1);
|
grub_memcpy (ptr, "GET ", sizeof ("GET ") - 1);
|
||||||
|
|
||||||
ptr = nb->tail;
|
ptr = nb->tail;
|
||||||
err = grub_netbuff_put (nb, grub_strlen (filename));
|
|
||||||
|
err = grub_netbuff_put (nb, grub_strlen (data->filename));
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
grub_free (data);
|
|
||||||
grub_netbuff_free (nb);
|
grub_netbuff_free (nb);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
grub_memcpy (ptr, filename, grub_strlen (filename));
|
grub_memcpy (ptr, data->filename, grub_strlen (data->filename));
|
||||||
|
|
||||||
ptr = nb->tail;
|
ptr = nb->tail;
|
||||||
err = grub_netbuff_put (nb, sizeof (" HTTP/1.1\r\nHost: ") - 1);
|
err = grub_netbuff_put (nb, sizeof (" HTTP/1.1\r\nHost: ") - 1);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
grub_free (data);
|
|
||||||
grub_netbuff_free (nb);
|
grub_netbuff_free (nb);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -264,7 +268,6 @@ http_open (struct grub_file *file, const char *filename)
|
||||||
err = grub_netbuff_put (nb, grub_strlen (file->device->net->server));
|
err = grub_netbuff_put (nb, grub_strlen (file->device->net->server));
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
grub_free (data);
|
|
||||||
grub_netbuff_free (nb);
|
grub_netbuff_free (nb);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -273,19 +276,30 @@ http_open (struct grub_file *file, const char *filename)
|
||||||
|
|
||||||
ptr = nb->tail;
|
ptr = nb->tail;
|
||||||
err = grub_netbuff_put (nb,
|
err = grub_netbuff_put (nb,
|
||||||
sizeof ("\r\nUser-Agent: " PACKAGE_STRING "\r\n\r\n")
|
sizeof ("\r\nUser-Agent: " PACKAGE_STRING "\r\n")
|
||||||
- 1);
|
- 1);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
grub_free (data);
|
|
||||||
grub_netbuff_free (nb);
|
grub_netbuff_free (nb);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
grub_memcpy (ptr, "\r\nUser-Agent: " PACKAGE_STRING "\r\n\r\n",
|
grub_memcpy (ptr, "\r\nUser-Agent: " PACKAGE_STRING "\r\n",
|
||||||
sizeof ("\r\nUser-Agent: " PACKAGE_STRING "\r\n\r\n") - 1);
|
sizeof ("\r\nUser-Agent: " PACKAGE_STRING "\r\n") - 1);
|
||||||
|
if (!initial)
|
||||||
file->not_easily_seekable = 1;
|
{
|
||||||
file->data = data;
|
ptr = nb->tail;
|
||||||
|
grub_snprintf ((char *) ptr,
|
||||||
|
sizeof ("Content-Range: bytes XXXXXXXXXXXXXXXXXXXX-"
|
||||||
|
"XXXXXXXXXXXXXXXXXXXX/XXXXXXXXXXXXXXXXXXXX\r\n"
|
||||||
|
"\r\n"),
|
||||||
|
"Content-Range: bytes %" PRIuGRUB_UINT64_T "-%"
|
||||||
|
PRIuGRUB_UINT64_T "/%" PRIuGRUB_UINT64_T "\r\n\r\n",
|
||||||
|
offset, data->file_size - 1, data->file_size);
|
||||||
|
grub_netbuff_put (nb, grub_strlen ((char *) ptr));
|
||||||
|
}
|
||||||
|
ptr = nb->tail;
|
||||||
|
grub_netbuff_put (nb, 2);
|
||||||
|
grub_memcpy (ptr, "\r\n", 2);
|
||||||
|
|
||||||
data->sock = grub_net_tcp_open (file->device->net->server,
|
data->sock = grub_net_tcp_open (file->device->net->server,
|
||||||
HTTP_PORT, http_receive,
|
HTTP_PORT, http_receive,
|
||||||
|
@ -293,7 +307,6 @@ http_open (struct grub_file *file, const char *filename)
|
||||||
file);
|
file);
|
||||||
if (!data->sock)
|
if (!data->sock)
|
||||||
{
|
{
|
||||||
grub_free (data);
|
|
||||||
grub_netbuff_free (nb);
|
grub_netbuff_free (nb);
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
}
|
}
|
||||||
|
@ -303,8 +316,7 @@ http_open (struct grub_file *file, const char *filename)
|
||||||
err = grub_net_send_tcp_packet (data->sock, nb, 1);
|
err = grub_net_send_tcp_packet (data->sock, nb, 1);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
grub_free (data);
|
grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT);
|
||||||
grub_net_tcp_close (data->sock);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,9 +328,81 @@ http_open (struct grub_file *file, const char *filename)
|
||||||
|
|
||||||
if (!data->headers_recv)
|
if (!data->headers_recv)
|
||||||
{
|
{
|
||||||
grub_net_tcp_close (data->sock);
|
grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT);
|
||||||
|
if (data->err)
|
||||||
|
{
|
||||||
|
char *str = data->errmsg;
|
||||||
|
err = grub_error (data->err, "%s", str);
|
||||||
|
grub_free (str);
|
||||||
|
return data->err;
|
||||||
|
}
|
||||||
|
return grub_error (GRUB_ERR_TIMEOUT, "timeout opening http");
|
||||||
|
}
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
http_seek (struct grub_file *file, grub_off_t off)
|
||||||
|
{
|
||||||
|
struct http_data *old_data, *data;
|
||||||
|
grub_err_t err;
|
||||||
|
old_data = file->data;
|
||||||
|
/* FIXME: Reuse socket? */
|
||||||
|
grub_net_tcp_close (old_data->sock, GRUB_NET_TCP_ABORT);
|
||||||
|
|
||||||
|
while (file->device->net->packs.first)
|
||||||
|
grub_net_remove_packet (file->device->net->packs.first);
|
||||||
|
|
||||||
|
data = grub_zalloc (sizeof (*data));
|
||||||
|
if (!data)
|
||||||
|
return grub_errno;
|
||||||
|
|
||||||
|
data->file_size = old_data->file_size;
|
||||||
|
data->size_recv = 1;
|
||||||
|
data->filename = old_data->filename;
|
||||||
|
if (!data->filename)
|
||||||
|
{
|
||||||
grub_free (data);
|
grub_free (data);
|
||||||
return grub_error (GRUB_ERR_TIMEOUT, "Time out opening http.");
|
return grub_errno;
|
||||||
|
}
|
||||||
|
grub_free (old_data);
|
||||||
|
|
||||||
|
err = http_establish (file, off, 0);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
grub_free (data->filename);
|
||||||
|
grub_free (data);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
http_open (struct grub_file *file, const char *filename)
|
||||||
|
{
|
||||||
|
grub_err_t err;
|
||||||
|
struct http_data *data;
|
||||||
|
|
||||||
|
data = grub_zalloc (sizeof (*data));
|
||||||
|
if (!data)
|
||||||
|
return grub_errno;
|
||||||
|
|
||||||
|
data->filename = grub_strdup (filename);
|
||||||
|
if (!data->filename)
|
||||||
|
{
|
||||||
|
grub_free (data);
|
||||||
|
return grub_errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
file->not_easily_seekable = 0;
|
||||||
|
file->data = data;
|
||||||
|
|
||||||
|
err = http_establish (file, 0, 1);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
grub_free (data->filename);
|
||||||
|
grub_free (data);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
file->size = data->file_size;
|
file->size = data->file_size;
|
||||||
|
|
||||||
|
@ -331,10 +415,10 @@ http_close (struct grub_file *file)
|
||||||
http_data_t data = file->data;
|
http_data_t data = file->data;
|
||||||
|
|
||||||
if (data->sock)
|
if (data->sock)
|
||||||
grub_net_tcp_close (data->sock);
|
grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT);
|
||||||
grub_free (data);
|
|
||||||
if (data->current_line)
|
if (data->current_line)
|
||||||
grub_free (data->current_line);
|
grub_free (data->current_line);
|
||||||
|
grub_free (data);
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -342,7 +426,8 @@ static struct grub_net_app_protocol grub_http_protocol =
|
||||||
{
|
{
|
||||||
.name = "http",
|
.name = "http",
|
||||||
.open = http_open,
|
.open = http_open,
|
||||||
.close = http_close
|
.close = http_close,
|
||||||
|
.seek = http_seek
|
||||||
};
|
};
|
||||||
|
|
||||||
GRUB_MOD_INIT (http)
|
GRUB_MOD_INIT (http)
|
||||||
|
|
|
@ -815,17 +815,17 @@ grub_net_poll_cards_idle_real (void)
|
||||||
static grub_ssize_t
|
static grub_ssize_t
|
||||||
grub_net_fs_read_real (grub_file_t file, char *buf, grub_size_t len)
|
grub_net_fs_read_real (grub_file_t file, char *buf, grub_size_t len)
|
||||||
{
|
{
|
||||||
grub_net_t sock = file->device->net;
|
grub_net_t net = file->device->net;
|
||||||
struct grub_net_buff *nb;
|
struct grub_net_buff *nb;
|
||||||
char *ptr = buf;
|
char *ptr = buf;
|
||||||
grub_size_t amount, total = 0;
|
grub_size_t amount, total = 0;
|
||||||
int try = 0;
|
int try = 0;
|
||||||
while (try <= 3)
|
while (try <= 3)
|
||||||
{
|
{
|
||||||
while (sock->packs.first)
|
while (net->packs.first)
|
||||||
{
|
{
|
||||||
try = 0;
|
try = 0;
|
||||||
nb = sock->packs.first->nb;
|
nb = net->packs.first->nb;
|
||||||
amount = nb->tail - nb->data;
|
amount = nb->tail - nb->data;
|
||||||
if (amount > len)
|
if (amount > len)
|
||||||
amount = len;
|
amount = len;
|
||||||
|
@ -840,7 +840,7 @@ grub_net_fs_read_real (grub_file_t file, char *buf, grub_size_t len)
|
||||||
if (amount == (grub_size_t) (nb->tail - nb->data))
|
if (amount == (grub_size_t) (nb->tail - nb->data))
|
||||||
{
|
{
|
||||||
grub_netbuff_free (nb);
|
grub_netbuff_free (nb);
|
||||||
grub_net_remove_packet (sock->packs.first);
|
grub_net_remove_packet (net->packs.first);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
nb->data += amount;
|
nb->data += amount;
|
||||||
|
@ -848,7 +848,7 @@ grub_net_fs_read_real (grub_file_t file, char *buf, grub_size_t len)
|
||||||
if (!len)
|
if (!len)
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
if (!sock->eof)
|
if (!net->eof)
|
||||||
{
|
{
|
||||||
try++;
|
try++;
|
||||||
grub_net_poll_cards (200);
|
grub_net_poll_cards (200);
|
||||||
|
@ -856,39 +856,59 @@ grub_net_fs_read_real (grub_file_t file, char *buf, grub_size_t len)
|
||||||
else
|
else
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
return total;
|
grub_error (GRUB_ERR_TIMEOUT, "timeout reading '%s'", net->name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_off_t
|
||||||
|
have_ahead (struct grub_file *file)
|
||||||
|
{
|
||||||
|
grub_net_t net = file->device->net;
|
||||||
|
grub_off_t ret = net->offset;
|
||||||
|
struct grub_net_packet *pack;
|
||||||
|
for (pack = net->packs.first; pack; pack = pack->next)
|
||||||
|
ret += pack->nb->tail - pack->nb->data;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_net_seek_real (struct grub_file *file, grub_off_t offset)
|
grub_net_seek_real (struct grub_file *file, grub_off_t offset)
|
||||||
{
|
{
|
||||||
grub_size_t len = offset - file->device->net->offset;
|
if (offset == file->device->net->offset)
|
||||||
|
|
||||||
if (!len)
|
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
|
|
||||||
if (file->device->net->offset > offset)
|
if (offset > file->device->net->offset)
|
||||||
{
|
{
|
||||||
grub_err_t err;
|
if (!file->device->net->protocol->seek || have_ahead (file) >= offset)
|
||||||
while (file->device->net->packs.first)
|
|
||||||
{
|
{
|
||||||
grub_netbuff_free (file->device->net->packs.first->nb);
|
grub_net_fs_read_real (file, NULL,
|
||||||
grub_net_remove_packet (file->device->net->packs.first);
|
offset - file->device->net->offset);
|
||||||
|
return grub_errno;
|
||||||
}
|
}
|
||||||
file->device->net->protocol->close (file);
|
return file->device->net->protocol->seek (file, offset);
|
||||||
|
|
||||||
file->device->net->packs.first = NULL;
|
|
||||||
file->device->net->packs.last = NULL;
|
|
||||||
file->device->net->offset = 0;
|
|
||||||
file->device->net->eof = 0;
|
|
||||||
err = file->device->net->protocol->open (file, file->device->net->name);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
len = offset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
grub_net_fs_read_real (file, NULL, len);
|
{
|
||||||
return GRUB_ERR_NONE;
|
grub_err_t err;
|
||||||
|
if (file->device->net->protocol->seek)
|
||||||
|
return file->device->net->protocol->seek (file, offset);
|
||||||
|
while (file->device->net->packs.first)
|
||||||
|
{
|
||||||
|
grub_netbuff_free (file->device->net->packs.first->nb);
|
||||||
|
grub_net_remove_packet (file->device->net->packs.first);
|
||||||
|
}
|
||||||
|
file->device->net->protocol->close (file);
|
||||||
|
|
||||||
|
file->device->net->packs.first = NULL;
|
||||||
|
file->device->net->packs.last = NULL;
|
||||||
|
file->device->net->offset = 0;
|
||||||
|
file->device->net->eof = 0;
|
||||||
|
err = file->device->net->protocol->open (file, file->device->net->name);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
grub_net_fs_read_real (file, NULL, offset);
|
||||||
|
return grub_errno;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_ssize_t
|
static grub_ssize_t
|
||||||
|
|
|
@ -56,7 +56,8 @@ struct grub_net_tcp_socket
|
||||||
int in_port;
|
int in_port;
|
||||||
int out_port;
|
int out_port;
|
||||||
int errors;
|
int errors;
|
||||||
int reseted;
|
int they_reseted;
|
||||||
|
int i_reseted;
|
||||||
grub_uint32_t my_start_seq;
|
grub_uint32_t my_start_seq;
|
||||||
grub_uint32_t my_cur_seq;
|
grub_uint32_t my_cur_seq;
|
||||||
grub_uint32_t their_start_seq;
|
grub_uint32_t their_start_seq;
|
||||||
|
@ -153,7 +154,7 @@ error (grub_net_tcp_socket_t sock)
|
||||||
{
|
{
|
||||||
struct unacked *unack, *next;
|
struct unacked *unack, *next;
|
||||||
|
|
||||||
if (sock->established && sock->error_hook)
|
if (sock->error_hook)
|
||||||
sock->error_hook (sock, sock->hook_data);
|
sock->error_hook (sock, sock->hook_data);
|
||||||
|
|
||||||
for (unack = sock->unack_first; unack; unack = next)
|
for (unack = sock->unack_first; unack; unack = next)
|
||||||
|
@ -217,7 +218,8 @@ tcp_send (struct grub_net_buff *nb, grub_net_tcp_socket_t socket)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
grub_net_tcp_close (grub_net_tcp_socket_t sock)
|
grub_net_tcp_close (grub_net_tcp_socket_t sock,
|
||||||
|
int discard_received)
|
||||||
{
|
{
|
||||||
struct grub_net_buff *nb_fin;
|
struct grub_net_buff *nb_fin;
|
||||||
struct tcphdr *tcph_fin;
|
struct tcphdr *tcph_fin;
|
||||||
|
@ -225,6 +227,9 @@ grub_net_tcp_close (grub_net_tcp_socket_t sock)
|
||||||
|
|
||||||
sock->i_closed = 1;
|
sock->i_closed = 1;
|
||||||
|
|
||||||
|
if (discard_received != GRUB_NET_TCP_CONTINUE_RECEIVING)
|
||||||
|
sock->recv_hook = NULL;
|
||||||
|
|
||||||
nb_fin = grub_netbuff_alloc (sizeof (*tcph_fin)
|
nb_fin = grub_netbuff_alloc (sizeof (*tcph_fin)
|
||||||
+ GRUB_NET_OUR_IPV4_HEADER_SIZE
|
+ GRUB_NET_OUR_IPV4_HEADER_SIZE
|
||||||
+ GRUB_NET_MAX_LINK_HEADER_SIZE);
|
+ GRUB_NET_MAX_LINK_HEADER_SIZE);
|
||||||
|
@ -254,6 +259,8 @@ grub_net_tcp_close (grub_net_tcp_socket_t sock)
|
||||||
tcph_fin->window = grub_cpu_to_be16 (0);
|
tcph_fin->window = grub_cpu_to_be16 (0);
|
||||||
tcph_fin->urgent = 0;
|
tcph_fin->urgent = 0;
|
||||||
err = tcp_send (nb_fin, sock);
|
err = tcp_send (nb_fin, sock);
|
||||||
|
if (discard_received == GRUB_NET_TCP_ABORT)
|
||||||
|
sock->i_reseted = 1;
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
grub_netbuff_free (nb_fin);
|
grub_netbuff_free (nb_fin);
|
||||||
|
@ -264,7 +271,7 @@ grub_net_tcp_close (grub_net_tcp_socket_t sock)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ack (grub_net_tcp_socket_t sock)
|
ack_real (grub_net_tcp_socket_t sock, int res)
|
||||||
{
|
{
|
||||||
struct grub_net_buff *nb_ack;
|
struct grub_net_buff *nb_ack;
|
||||||
struct tcphdr *tcph_ack;
|
struct tcphdr *tcph_ack;
|
||||||
|
@ -291,9 +298,18 @@ ack (grub_net_tcp_socket_t sock)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tcph_ack = (void *) nb_ack->data;
|
tcph_ack = (void *) nb_ack->data;
|
||||||
tcph_ack->ack = grub_cpu_to_be32 (sock->their_cur_seq);
|
if (res)
|
||||||
tcph_ack->flags = grub_cpu_to_be16 ((5 << 12) | TCP_ACK);
|
{
|
||||||
tcph_ack->window = grub_cpu_to_be16 (sock->my_window);
|
tcph_ack->ack = grub_cpu_to_be32 (0);
|
||||||
|
tcph_ack->flags = grub_cpu_to_be16 ((5 << 12) | TCP_RST);
|
||||||
|
tcph_ack->window = grub_cpu_to_be16 (0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tcph_ack->ack = grub_cpu_to_be32 (sock->their_cur_seq);
|
||||||
|
tcph_ack->flags = grub_cpu_to_be16 ((5 << 12) | TCP_ACK);
|
||||||
|
tcph_ack->window = grub_cpu_to_be16 (sock->my_window);
|
||||||
|
}
|
||||||
tcph_ack->urgent = 0;
|
tcph_ack->urgent = 0;
|
||||||
tcph_ack->src = grub_cpu_to_be16 (sock->in_port);
|
tcph_ack->src = grub_cpu_to_be16 (sock->in_port);
|
||||||
tcph_ack->dst = grub_cpu_to_be16 (sock->out_port);
|
tcph_ack->dst = grub_cpu_to_be16 (sock->out_port);
|
||||||
|
@ -305,6 +321,18 @@ ack (grub_net_tcp_socket_t sock)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ack (grub_net_tcp_socket_t sock)
|
||||||
|
{
|
||||||
|
ack_real (sock, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
reset (grub_net_tcp_socket_t sock)
|
||||||
|
{
|
||||||
|
ack_real (sock, 1);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
grub_net_tcp_retransmit (void)
|
grub_net_tcp_retransmit (void)
|
||||||
{
|
{
|
||||||
|
@ -434,6 +462,7 @@ grub_net_tcp_accept (grub_net_tcp_socket_t sock,
|
||||||
tcph->flags = grub_cpu_to_be16 ((5 << 12) | TCP_SYN | TCP_ACK);
|
tcph->flags = grub_cpu_to_be16 ((5 << 12) | TCP_SYN | TCP_ACK);
|
||||||
tcph->window = grub_cpu_to_be16 (sock->my_window);
|
tcph->window = grub_cpu_to_be16 (sock->my_window);
|
||||||
tcph->urgent = 0;
|
tcph->urgent = 0;
|
||||||
|
sock->established = 1;
|
||||||
tcp_socket_register (sock);
|
tcp_socket_register (sock);
|
||||||
err = tcp_send (nb_ack, sock);
|
err = tcp_send (nb_ack, sock);
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -555,7 +584,7 @@ grub_net_tcp_open (char *server,
|
||||||
{
|
{
|
||||||
grub_list_remove (GRUB_AS_LIST_P (&tcp_sockets),
|
grub_list_remove (GRUB_AS_LIST_P (&tcp_sockets),
|
||||||
GRUB_AS_LIST (socket));
|
GRUB_AS_LIST (socket));
|
||||||
if (socket->reseted)
|
if (socket->they_reseted)
|
||||||
grub_error (GRUB_ERR_NET_PORT_CLOSED, "port closed");
|
grub_error (GRUB_ERR_NET_PORT_CLOSED, "port closed");
|
||||||
else
|
else
|
||||||
grub_error (GRUB_ERR_NET_NO_ANSWER, "no answer");
|
grub_error (GRUB_ERR_NET_NO_ANSWER, "no answer");
|
||||||
|
@ -693,7 +722,7 @@ grub_net_recv_tcp_packet (struct grub_net_buff *nb,
|
||||||
|
|
||||||
if (grub_be_to_cpu16 (tcph->flags) & TCP_RST)
|
if (grub_be_to_cpu16 (tcph->flags) & TCP_RST)
|
||||||
{
|
{
|
||||||
sock->reseted = 1;
|
sock->they_reseted = 1;
|
||||||
|
|
||||||
error (sock);
|
error (sock);
|
||||||
|
|
||||||
|
@ -725,7 +754,7 @@ grub_net_recv_tcp_packet (struct grub_net_buff *nb,
|
||||||
grub_free (unack);
|
grub_free (unack);
|
||||||
}
|
}
|
||||||
sock->unack_first = unack;
|
sock->unack_first = unack;
|
||||||
if (!sock->unack_last)
|
if (!sock->unack_first)
|
||||||
sock->unack_last = NULL;
|
sock->unack_last = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -735,6 +764,12 @@ grub_net_recv_tcp_packet (struct grub_net_buff *nb,
|
||||||
grub_netbuff_free (nb);
|
grub_netbuff_free (nb);
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
if (sock->i_reseted)
|
||||||
|
{
|
||||||
|
reset (sock);
|
||||||
|
grub_netbuff_free (nb);
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
err = grub_priority_queue_push (sock->pq, &nb);
|
err = grub_priority_queue_push (sock->pq, &nb);
|
||||||
if (err)
|
if (err)
|
||||||
|
|
|
@ -204,6 +204,7 @@ struct grub_net_app_protocol
|
||||||
int (*hook) (const char *filename,
|
int (*hook) (const char *filename,
|
||||||
const struct grub_dirhook_info *info));
|
const struct grub_dirhook_info *info));
|
||||||
grub_err_t (*open) (struct grub_file *file, const char *filename);
|
grub_err_t (*open) (struct grub_file *file, const char *filename);
|
||||||
|
grub_err_t (*seek) (struct grub_file *file, grub_off_t off);
|
||||||
grub_err_t (*close) (struct grub_file *file);
|
grub_err_t (*close) (struct grub_file *file);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -53,8 +53,15 @@ grub_net_send_tcp_packet (const grub_net_tcp_socket_t socket,
|
||||||
struct grub_net_buff *nb,
|
struct grub_net_buff *nb,
|
||||||
int push);
|
int push);
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
GRUB_NET_TCP_CONTINUE_RECEIVING,
|
||||||
|
GRUB_NET_TCP_DISCARD,
|
||||||
|
GRUB_NET_TCP_ABORT
|
||||||
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
grub_net_tcp_close (grub_net_tcp_socket_t sock);
|
grub_net_tcp_close (grub_net_tcp_socket_t sock, int discard_received);
|
||||||
|
|
||||||
grub_err_t
|
grub_err_t
|
||||||
grub_net_tcp_accept (grub_net_tcp_socket_t sock,
|
grub_net_tcp_accept (grub_net_tcp_socket_t sock,
|
||||||
|
|
Loading…
Reference in a new issue