From fbdee79b1729f432e4673a5088b20509be5e032b Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Fri, 1 Apr 2011 05:22:41 -0300 Subject: [PATCH] Add generic functions to read and seek in network file. Allocate socket with network and adress information. --- grub-core/net/net.c | 164 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) diff --git a/grub-core/net/net.c b/grub-core/net/net.c index ab6b39261..8c9229915 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -17,8 +17,12 @@ */ #include +#include +#include +#include #include #include +#include #include #include #include @@ -40,6 +44,7 @@ struct grub_net_route struct grub_net_route *grub_net_routes = NULL; struct grub_net_network_level_interface *grub_net_network_level_interfaces = NULL; struct grub_net_card *grub_net_cards = NULL; +struct grub_net_card_driver *grub_net_card_drivers = NULL; struct grub_net_network_level_protocol *grub_net_network_level_protocols = NULL; static inline void @@ -538,6 +543,7 @@ grub_cmd_listcards (struct grub_command *cmd __attribute__ ((unused)), } grub_net_app_level_t grub_net_app_level_list; +struct grub_net_socket *grub_net_sockets; static grub_net_t grub_net_open_real (const char *name) @@ -570,6 +576,159 @@ grub_net_open_real (const char *name) return NULL; } +static grub_err_t +grub_net_file_open_real (struct grub_file *file, const char *name) +{ + grub_err_t err; + grub_net_network_level_address_t addr; + struct grub_net_network_level_interface *inf; + grub_net_network_level_address_t gateway; + grub_net_socket_t socket; + static int port = 25300; + + err = grub_net_resolve_address (file->device->net->name + + sizeof (file->device->net->protocol->name) + 1, &addr); + if (err) + return err; + + err = grub_net_route_address (addr, &gateway, &inf); + if (err) + return err; + + if ((socket = (grub_net_socket_t) grub_malloc (sizeof (*socket))) == NULL) + return GRUB_ERR_OUT_OF_MEMORY; + + socket->inf = inf; + socket->out_nla = addr; + socket->in_port = port++; + socket->status = 0; + socket->app = file->device->net->protocol; + socket->packs = NULL; + file->device->net->socket = socket; + grub_net_socket_register (socket); + + if ((err = file->device->net->protocol->open (file,name))) + goto fail; + + return GRUB_ERR_NONE; +fail: + grub_net_socket_unregister (socket); + grub_free (socket); + return err; + +} + +static grub_err_t +receive_packets (struct grub_net_card *card) +{ + /* Maybe should be better have a fixed number of packets for each card + and just mark them as used and not used. */ + struct grub_net_buff *nb; + nb = grub_netbuff_alloc (1500); + if (!nb) + return grub_errno; + + card->driver->recv (card, nb); + return GRUB_ERR_NONE; +} + +void +grub_net_pool_cards (unsigned time) +{ + struct grub_net_card *card; + grub_uint64_t start_time; + FOR_NET_CARDS (card) + { + start_time = grub_get_time_ms (); + while( (grub_get_time_ms () - start_time) < time) + receive_packets (card); + } +} + +static grub_ssize_t +process_packets (grub_file_t file, void *buf, grub_size_t len, + void *NESTED_FUNC_ATTR (hook) (void *dest, const void *src, grub_size_t n)) +{ + grub_net_socket_t sock = file->device->net->socket; + struct grub_net_buff *nb; + char *ptr = (char *) buf; + grub_size_t amount, total = 0; + int try = 0; + while (try <= 3) + { + while (sock->packs->first) + { + try = 0; + nb = sock->packs->first->nb; + amount = (grub_size_t)(len <= (grub_size_t) (nb->tail - nb->data))? len :(grub_size_t)(nb->tail - nb->data); + len -= amount; + total += amount; + hook (ptr, nb->data, amount); + ptr += amount; + if (amount == (grub_size_t) (nb->tail - nb->data)) + { + grub_netbuff_free (nb); + grub_net_remove_packet (sock->packs->first); + } + else + nb->data += amount; + + if (!len) + return total; + } + if (sock->status == 1) + { + try++; + grub_net_pool_cards (200); + } + else + return total; + } + return total; +} + + +/* Read from the packets list*/ +static grub_ssize_t +grub_net_read_real (grub_file_t file, void *buf, grub_size_t len ) +{ + auto void *NESTED_FUNC_ATTR memcpy_hook (void *dest, const void *src, grub_size_t n); + void *NESTED_FUNC_ATTR memcpy_hook (void *dest __attribute__ ((unused)), const void *src __attribute__ ((unused)), + grub_size_t n __attribute__ ((unused))) + { + return grub_memcpy (dest, src, n); + } + return process_packets (file, buf, len, memcpy_hook); +} + +/* Read from the packets list*/ +static grub_err_t +grub_net_seek_real (struct grub_file *file, grub_off_t offset) +{ + grub_net_socket_t sock = file->device->net->socket; + struct grub_net_buff *nb; + grub_size_t len = offset - file->offset; + + if (!len) + return GRUB_ERR_NONE; + + /* We cant seek backwards past the current packet. */ + if (file->offset > offset) + { + nb = sock->packs->first->nb; + return grub_netbuff_push (nb, file->offset - offset); + } + + auto void *NESTED_FUNC_ATTR dummy (void *dest, const void *src, grub_size_t n); + void *NESTED_FUNC_ATTR dummy (void *dest __attribute__ ((unused)), const void *src __attribute__ ((unused)), + grub_size_t n __attribute__ ((unused))) + { + return NULL; + } + process_packets (file, NULL, len, dummy); + return GRUB_ERR_NONE; +} + static char * grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)), const char *val __attribute__ ((unused))) @@ -857,6 +1016,9 @@ GRUB_MOD_INIT(net) N_("retrieve DHCP option and save it into VAR. If VAR is - then print the value.")); grub_net_open = grub_net_open_real; + grub_file_net_open = grub_net_file_open_real; + grub_file_net_read = grub_net_read_real; + grub_file_net_seek = grub_net_seek_real; } GRUB_MOD_FINI(net) @@ -869,4 +1031,6 @@ GRUB_MOD_FINI(net) grub_unregister_command (cmd_lscards); grub_unregister_command (cmd_getdhcp); grub_net_open = NULL; + grub_file_net_read = NULL; + grub_file_net_open = NULL; }