Skip to content
Extraits de code Groupes Projets
Valider f9f1b64d rédigé par Vany Ingenzi's avatar Vany Ingenzi
Parcourir les fichiers

Modified utils and added the code for the inginious task

parent d18c9550
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
......@@ -44,11 +44,11 @@ int create_socket(struct sockaddr_in6 *source_addr, int src_port, struct sockadd
/* Block the caller until a message is received on sfd,
* and connect the socket to the source addresse of the received message
* @sfd: a file descriptor to a bound socket but not yet connected
* @buffer : a non null buffer where it writes the received message.
* @len: after reading the message it sents the amount bytes read in len.
* @return: 0 in case of success, -1 otherwise
* @POST: This call is idempotent, it does not 'consume' the data of the message,
* and could be repeated several times blocking only at the first call.
*/
int wait_for_client(int sfd, int MAX_MESSAGE_SIZE, char * buffer, ssize_t * len);
int wait_for_client(int sfd);
#endif
\ No newline at end of file
/**
* @file receiver.h
* @brief This header contains all the structures and functions definitions that ae going to be used by the receiver.c
*/
\ No newline at end of file
*/
#ifndef __RECEIVER_UTILS_
#define __RECEIVER_UTILS_
/* We are using 8 bits to encode the seqnum therefore to fight redondance our window is of 2**(8)/2 */
#define MAX_SELECTIVE_REPEAT_WINDOW 8
/* Represent the receiver's connection state */
typedef struct __attribute__((__packed__))
{
} con_state_t;
/**
* Loop reading on socket and printing to the stdout
* @sfd : The socket file descriptor. It is both bound and connected.
* @return: as soon as the whole transfer is done.
*/
void receiver_read_write_loop(int sfd);
#endif
\ No newline at end of file
/**
* @file receiver_utils.h
* @brief This header contains utils will be used by the receiver
* @date 2022-03-17
*/
#ifndef __RECEIVER_UTILS_
#define __RECEIVER_UTILS_
/* We are using 8 bits to encode the seqnum therefore to fight redondance our window is of 2**(8)/2 */
#define MAX_SELECTIVE_REPEAT_WINDOW 8
/* Represent the receiver's connection state */
typedef struct __attribute__((__packed__))
{
} con_state_t;
/**
* Loop reading on socket and printing to the stdout
* @sfd : The socket file descriptor. It is both bound and connected.
* @return: as soon as the whole transfer is done.
*/
void receiver_read_write_loop(int sfd);
#endif
\ No newline at end of file
Fichier ajouté
Fichier ajouté
......@@ -89,22 +89,18 @@ int create_socket(struct sockaddr_in6 *source_addr, int src_port, struct sockadd
return -1;
}
int wait_for_client(int sfd, int MAX_MESSAGE_SIZE, char * buffer, ssize_t * len)
int wait_for_client(int sfd)
{
int MAX_MESSAGE_SIZE = 1024;
uint8_t buff[MAX_MESSAGE_SIZE]; // allocate the receive buffer on the stack
struct sockaddr_storage peer_addr; // allocate the peer's address on the stack. It will be initialized when we receive a message
socklen_t peer_addr_len = sizeof(struct sockaddr_storage); // variable that will contain the length of the peer's address
*len = recvfrom(sfd, buffer, MAX_MESSAGE_SIZE, MSG_PEEK, (struct sockaddr *) &peer_addr, &peer_addr_len);
if (*len == -1)
{
ERROR("On recvfrom while waiting for client");
ssize_t amount_read = recvfrom(sfd, buff, MAX_MESSAGE_SIZE, MSG_PEEK, (struct sockaddr *) &peer_addr, &peer_addr_len);
if (amount_read == -1){
return -1;
}
int err = connect(sfd, (struct sockaddr *) &peer_addr, sizeof(struct sockaddr_storage));
int err = connect(sfd, (struct sockaddr *) &peer_addr, sizeof(struct sockaddr_storage));
if (err != EISCONN && err != 0)
{
ERROR("When connecting to client");
return -1;
}
return 0;
}
\ No newline at end of file
......@@ -13,7 +13,7 @@
#include "log.h"
#include "packet_interface.h"
#include "our_utils.h"
#include "receiver_utils.h"
#include "receiver.h"
int print_usage(char *prog_name) {
ERROR("Usage:\n\t%s [-s stats_filename] listen_ip listen_port", prog_name);
......
......@@ -3,7 +3,7 @@
#include "packet_interface.h"
#include <poll.h>
#include "our_utils.h"
#include "receiver_utils.h"
#include "receiver.h"
int send_data_if_inneed()
{
......@@ -74,7 +74,7 @@ int connect_to_a_client(int sfd, pkt_t * init_pkt)
char * buffer[PKT_MAX_LEN];
ssize_t written_in_buffer;
// We suppose that the first contact is going to be our client no need to check for more
int err = wait_for_client(sfd, PKT_MAX_LEN, (char *)buffer, &written_in_buffer);
int err = wait_for_client(sfd);
if (err != 0) return -1;
DEBUG_DUMP(buffer, written_in_buffer);
......@@ -105,6 +105,7 @@ void receiver_read_write_loop(int sfd)
int err = connect_to_a_client(sfd, pkt);
if (err == 0)
return;
// Handle initial packet.
err = fwrite((void *) pkt_get_payload(pkt), sizeof(char), pkt_get_length(pkt), stdout);
......
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <poll.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
/*************************** Utilities ******************************/
/*************************** Start Q1 *******************************/
/* Resolve the resource name to an usable IPv6 address
* @address: The name to resolve
* @rval: Where the resulting IPv6 address descriptor should be stored
* @return: NULL if it succeeded, or a pointer towards
* a string describing the error if any.
* (const char* means the caller cannot modify or free the return value,
* so do not use malloc!)
*/
const char * real_address(const char *address, struct sockaddr_in6 *rval)
{
struct addrinfo hints;
struct addrinfo *result;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_CANONNAME;
hints.ai_protocol = 0;
int res = getaddrinfo(address, NULL, &hints, &result);
if ( res != 0 )
return gai_strerror(res);
rval = (struct sockaddr_in6 *) memcpy( (void *) rval, result->ai_addr, sizeof(struct sockaddr_in6));
freeaddrinfo(result);
return NULL;
}
/*************************** End Q1 *******************************/
/*************************** Start Q2 *****************************/
void ipv6_to_str_unexpanded(char *str, const struct in6_addr *addr) {
sprintf(str, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
(int)addr->s6_addr[0], (int)addr->s6_addr[1],
(int)addr->s6_addr[2], (int)addr->s6_addr[3],
(int)addr->s6_addr[4], (int)addr->s6_addr[5],
(int)addr->s6_addr[6], (int)addr->s6_addr[7],
(int)addr->s6_addr[8], (int)addr->s6_addr[9],
(int)addr->s6_addr[10], (int)addr->s6_addr[11],
(int)addr->s6_addr[12], (int)addr->s6_addr[13],
(int)addr->s6_addr[14], (int)addr->s6_addr[15]);
}
int create_socket_bind(struct sockaddr_in6 * source_addr)
{
// TODO: Create a IPv6 socket supporting datagrams
int sock = socket(AF_INET6, SOCK_DGRAM, 0);
// TODO: Bind it to the source
int err = bind(sock, (struct sockaddr *) source_addr, sizeof(struct sockaddr_in6));
if (err == -1)
return -1;
char text[100];
ipv6_to_str_unexpanded(text, &(source_addr->sin6_addr));
//const char * addr_str = inet_ntop(AF_INET6, (void *) &(source_addr->sin6_addr), text, 100);
fprintf(stderr, "Successfully bound to IPv6 address : %s, port : %d\n", text, ntohs(source_addr->sin6_port));
return sock;
}
int create_socket_connect(struct sockaddr_in6 * dest_addr)
{
int sock = socket(AF_INET6, SOCK_DGRAM, 0);
int err = connect(sock, (struct sockaddr *) dest_addr, sizeof(*dest_addr));
if (err == -1)
return -1;
char text[100];
ipv6_to_str_unexpanded(text, &(dest_addr->sin6_addr));
fprintf(stderr, "Successfully connected to IPv6 addresss: %s, port : %d\n", text, ntohs(dest_addr->sin6_port));
return sock;
}
/* Creates a socket and initialize it
* @source_addr: if !NULL, the source address that should be bound to this socket
* @src_port: if >0, the port on which the socket is listening
* @dest_addr: if !NULL, the destination address to which the socket should send data
* @dst_port: if >0, the destination port to which the socket should be connected
* @return: a file descriptor number representing the socket,
* or -1 in case of error (explanation will be printed on stderr)
*/
int create_socket(struct sockaddr_in6 *source_addr, int src_port, struct sockaddr_in6 *dest_addr, int dst_port)
{
if ( source_addr != NULL && dest_addr == NULL )
{
source_addr->sin6_port = htons(src_port);
return create_socket_bind(source_addr);
} else if ( source_addr == NULL && dest_addr != NULL ){
dest_addr->sin6_port = htons(dst_port);
return create_socket_connect(dest_addr);
}
return -1;
}
/*************************** End Q2 *******************************/
/*************************** Start Q3 *****************************/
int handle_event(struct pollfd * pfd, ssize_t MAX_SIZE, char * buff)
{
if (pfd->revents & POLLIN){
ssize_t read_bytes = read(pfd->fd, (void *) buff, MAX_SIZE);
if (read_bytes == -1)
return 0;
size_t err = fwrite("Incoming : \n\t", sizeof(char), 14, stderr);
err = fflush(stderr);
err = fwrite((void *) buff, sizeof(char), read_bytes, stdout);
if (err == 0)
fprintf(stderr, "Nonesense\n");
err = fflush(stdout);
return 1;
} else if (pfd->events & POLLHUP){ /*EOF or Error*/
fprintf(stderr, "Error...\n");
return 0;
} else { /* POLLOUT */
size_t err;
size_t read_bytes = fread(buff, sizeof(char), MAX_SIZE, stdin);
if (read_bytes != 0)
{
err = write(pfd->fd, (void *) buff, read_bytes);
if (err == 0)
return 0;
err = fwrite("\n Sent\n", sizeof(char), 8, stderr);
}
err = fflush(stderr);
return 1;
}
}
/* Loop reading a socket and printing to stdout,
* while reading stdin and writing to the socket
* @sfd: The socket file descriptor. It is both bound and connected.
* @return: as soon as stdin signals EOF
*/
void read_write_loop(int sfd)
{
struct pollfd * pfds;
pfds = (struct pollfd *) calloc(2, sizeof(struct pollfd));
if (pfds == NULL)
return;
pfds[0].fd = sfd;
pfds[0].events = POLLIN | POLLOUT;
pfds[1].fd = 0; // stdin is defined to be file descriptor 0
pfds[1].events = POLLIN ;
int nb_open_fds = 2;
int MAX_SIZE = 1024; // Bytes
char buff[MAX_SIZE];
size_t writen;
while (nb_open_fds > 1)
{
int ready = poll(pfds, 2, -1);
if (ready == -1)
return;
if (pfds[0].revents & POLLIN){
ssize_t read_bytes = read(pfds[0].fd, (void *) buff, MAX_SIZE);
if (read_bytes == -1)
return;
writen = fwrite((void *) buff, sizeof(char), read_bytes, stdout);
writen = fflush(stdout);
} else if ((pfds[0].revents & POLLHUP) || (pfds[0].revents & POLLERR)){
nb_open_fds--;
} else if ((pfds[0].revents & POLLOUT) && (pfds[1].revents & POLLIN)){
size_t read_bytes = fread(buff, sizeof(char), 1, stdin);
writen = fflush(stdin);
writen = write(pfds[0].fd, (void *) buff, read_bytes);
size_t e = -1;
if (writen == e || feof(stdin) != 0)
return;
}
}
}
/*************************** End Q3 *******************************/
/*************************** Start Q4 *****************************/
/* Block the caller until a message is received on sfd,
* and connect the socket to the source addresse of the received message
* @sfd: a file descriptor to a bound socket but not yet connected
* @return: 0 in case of success, -1 otherwise
* @POST: This call is idempotent, it does not 'consume' the data of the message,
* and could be repeated several times blocking only at the first call.
*/
int wait_for_client(int sfd)
{
int MAX_MESSAGE_SIZE = 1024;
uint8_t buff[MAX_MESSAGE_SIZE]; // allocate the receive buffer on the stack
struct sockaddr_storage peer_addr; // allocate the peer's address on the stack. It will be initialized when we receive a message
socklen_t peer_addr_len = sizeof(struct sockaddr_storage); // variable that will contain the length of the peer's address
ssize_t amount_read = recvfrom(sfd, buff, MAX_MESSAGE_SIZE, MSG_PEEK, (struct sockaddr *) &peer_addr, &peer_addr_len);
if (amount_read == -1){
return -1;
}
int err = connect(sfd, (struct sockaddr *) &peer_addr, sizeof(struct sockaddr_storage));
if (err != EISCONN && err != 0)
return -1;
return 0;
}
/*************************** End Q4 *******************************/
int main(int argc, char const *argv[])
{
if (argc != 4)
{
fprintf(stderr, "./get_ipv6_addr <name_to_resolve> <port> <flag>\n - <flag> ::= c `|` s\n");
return (EXIT_SUCCESS);
}
// Name resolving
struct sockaddr_in6 * addr = (struct sockaddr_in6 *) malloc(sizeof(struct sockaddr_in6));
const char * res = real_address(argv[1], addr);
if (res != NULL)
{
fprintf(stderr, "An error occured when name resolving :\n\t%s\n", res);
return (EXIT_FAILURE);
}
// Socket Binding or Connecting
int socket;
if (strncasecmp(argv[3], "c", 1) == 0)
{
socket = create_socket(NULL, 0, addr, atoi(argv[2]));
} else if (strncasecmp(argv[3], "s", 1) == 0)
{
socket = create_socket(addr, atoi(argv[2]), NULL, 0);
wait_for_client(socket);
}
if (socket == -1)
{
fprintf(stderr, "An error occured when connecting/binding to address\n");
return (EXIT_FAILURE);
}
read_write_loop(socket);
close(socket);
// Writing and reading
return (EXIT_SUCCESS );
}
\ No newline at end of file
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Veuillez vous inscrire ou vous pour commenter