Está en la página 1de 37

UNIVERSIDAD PRIVADA BOLIVIANA

FACULTAD DE INGENIERÍA Y
ARQUITECTURA

Proyecto Final

Estudiantes : Ignacio Ballón

Santiago Fuentes

Carlos Fuentes

Alejandro Jaimes

Mathias Nieva

Javier Soruco

Materia : Teleinformática

Cochabamba, 28 de Marzo de 2021


Proyecto Final: Servicio de “streaming” para ESP32

1. PROCESO DE COMUNICACIÓN

A continuación se detalla el proceso de comunicación del protocolo propuesto, es


importante tomar en cuenta que este protocolo está pensado para ser aplicado sobre TCP,
por ende, se intuye que la primera solicitud de cada elemento que cumple el rol de cliente
se realiza el respectivo handshake.

1.1 Proxy storage

Una vez que el servidor proxy y el cliente finalizan un handshake TCP, la primera tarea del
servidor proxy es enviarle al cliente codificado en 2 bytes un entero sin signo que representa
el número de imágenes disponibles.

1.2 Client request:

El cliente solicita el número de frame al proxy server, para hacerlo, este envía un número
entero sin signo representado en 2 bytes. Una vez verificada la conexión con el servidor
proxy cambiará a un estado de espera de los datos.

1.3 Proxy request:

El servidor proxy rescata de su base de datos el frame solicitado por el cliente, y lo envía al
servidor de conversión, manda como header el tamaño total del archivo en bytes codificada
como entero sin signo en 4 bytes, así el servidor de conversión puede saber cuando la
imagen completa ha sido recibida y cambia a un estado de espera para recibir los datos del
header del servidor de conversión.

1.4 Conversion response


El servidor de conversión recibe primero el header del proxy que especifica el tamaño del
archivo bmp. Una vez se lee todo el archivo bmp se procede a extraer información
necesaria de los headers propios del bmp, esta información es: el largo, el alto, el tamaño
del raw bitmap data y la paleta de colores.
Como todas las imagenes son en blanco y negro se puso como estandar manejar la
profundidad de color en 1 bit por pixel.
Una vez se extrae la información se procede al cálculo del tamaño de la “fila” que incluye el
padding para que sea múltiplo de 4 bytes, al obtener cuantos bytes son utilizados para
padding se obtiene el tamaño de la data que en realidad se utiliza y en cómo se maneja 1
bpp, en reiteradas ocasiones no se toman bytes completos de data y gracias a este cálculo
se puede evitar problemas con invertir bits innecesarios.
Empleando un algoritmo propio se extrae la data pura, ignorando el padding, del raw bitmap
data y esta información es invertida o no dependiendo de la paleta de colores que se definió
anteriormente. Una vez terminado este proceso se hace el cálculo de los bits necesarios
que se están tomando del último byte, que siendo el caso, solo se tome la información hasta
esa cantidad y el resto se le coloque un valor nulo.
Al terminar este proceso se obtiene el bitmap y se hace el cálculo del checksum para que se
pueda garantizar la comunicación.
El servidor de conversión envía el bitmap al servidor proxy, para esto incluye los siguientes
headers:
- El tamaño total del bitmap codificado en 4 bytes como entero sin signo, así el proxy
puede determinar cuando el archivo ha sido recibido en su totalidad.
- El ancho del bitmap codificado en 4 bytes como entero sin signo, dato necesario
para la impresión en cliente ESP32.
- La altura del bitmap codificado en 4 bytes como entero sin signo, dato necesario
para la impresión en cliente ESP32.
- El checksum codificado en 1 byte, dato necesario para garantizar que la imagen no
llegó corrupta.

1.5 Proxy response:


El servidor proxy hace el cálculo de su propio checksum para compararlo con el recibido del
servidor de conversión, y en el caso de que sean iguales hace un forward de la información
recibida por el servidor de conversión hacia el cliente ESP32 y en caso que no, vuelve a
enviar el frame al servidor de conversión.

1.6 Client print:


El cliente recibe 4 headers indicando el tamaño, el ancho, la altura y el checksum del bitmap
que llegará. A continuación recibirá los bytes del bitmap usando el valor del header tamaño
para leer la cantidad completa de bytes. Ahora el cliente realizará su propio checksum y lo
comparará con el valor del header checksum que recibió. Si ambos checksums son iguales,
el cliente imprimirá el bitmap usando los valores de los headers ancho y altura y pedirá al
proxy el siguiente frame para repetir todo el proceso cíclicamente. Si los checksums no son
iguales no imprimirá el bitmap y el cliente le pedirá al proxy reenviar el frame para repetir el
proceso.

Lo descrito anteriormente se repite de manera cíclica.

Etapa Información Tamaño Tipo de dato


necesaria

Proxy storage Número de imágenes 2 bytes uint16_t


disponibles

Cliente solicita archivo Número de secuencia 2 bytes uint16_t


a proxy server de la imagen

Proxy envía archivo Tamaño total del 4 bytes uint32_t


BMP al servidor de archivo (completo)
conversión
Archivo BMP con todos Variable bitmap (raw)
sus headers

El servidor de Tamaño total del 4 bytes uint32_t


conversión envía el bitmap
bitmap
bitmap width 4 bytes uint32_t

bitmap height 4 bytes uint32_t


checksum 1 byte unint8_t

bitmap Variable bitmap(raw)

El proxy reenvía el Tamaño total del 4 bytes uint32_t


bitmap al cliente bitmap

bitmap width 4 bytes uint32_t

bitmap height 4 bytes uint32_t

checksum 1 byte uint8_t

bitmap Variable bitmap(raw)

Lectura BMP Carlos Fuentes y Santiago Fuentes

Conversión request

Recepción proxy cliente y obtención BMP Javier Soruco y Ignacio Ballón

Obtener el file size y enviarlo con el archivo

Envío del client request (cíclico) Alejandro Jaimes y Mathias Nieva

Recibir headers y bitmap e imprimir

Puertos de comunicaciones:

Client - Proxy 40000

Proxy - Converter 40001

2. Instrucciones de instalacion:
En primer lugar se debe cambiar la IP del servidor proxy en el archivo “finalClient.ino”,
también se debe cambiar el SSID y contraseña de la red a usar, en caso de tener otro
modelo de ESP32 también deben cambiarse los valores de los pines LCD.
El servidor proxy empieza contando el número de archivos en la carpeta proxy frames, por
ende esta carpeta debe estar presente para poder compilar el servidor proxy, se debe
respetar la estructura:
/proyectoFinal/Scripts/proxy.c
/proyectoFinal/PROXY-FRAMES
El servidor proxy obtiene su ip (y la del servidor de conversión) de manera automática del
interfaz enp0s3, en caso de usar otro interfaz la variable global SERVER_INTERFACE
debe ser cambiada en el archivo proxy.c

Se puede compilar el proxy con el comando:


gcc -o proxy proxy.c

El servidor de conversión requiere usar el siguiente comando para compilar:


gcc -o convertidor convertidor.c -lm

Finalmente, para ejecutar el programa, se requiere que primero se ejecute el servidor de


conversión, posteriormente el proxy y el cliente ESP32 al final, las ejecuciones no requieren
parámetros.

3.Resultados
Servidor de conversión:
Inicialmente el servidor está escuchando en el puerto 40001, esperando una conexión del
proxy.

Una vez recibe un request del proxy, este empieza a leer los datos del bitmap y mandarlos
en una response.
Servidor proxy
Cuando el servidor proxy se ejecuta, empieza contando la cantidad de archivos disponibles,
posteriormente se conecta al servidor de conversión y se queda a la espera de que el
cliente inicie la conexión.

Luego de conectarse con el cliente, este le envia el numero de imágenes disponibles en el


servidor, luego se queda a la espera de una request, una vez recibe una, busca en sus
datos la imagen pedida y la manda al servidor de conversión con su respectivo header y
checksum, luego se queda a la espera de la respuesta, una vez recibida, revisa el
checksum, en caso de ser correcto, envía la información al cliente, caso contrario vuelve a
hacer la request al conversor.
Cliente ESP-32

El cliente inicia estableciendo una conexión con el proxy, una vez lo hace, lee dos bytes, los
cuales son el número total de imágenes disponibles, luego empieza a pedir estas imágenes
de manera incremental y cíclica al proxy, una vez recibe el resultado, revisa el checksum, en
caso de todo estar correcto, imprime la imagen, caso contrario, vuelve a pedir la imagen al
proxy.
4. ANEXOS

Código de Cliente:
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <MD5.h>
#include <ctype.h>
#include <SPI.h>
#include <WiFi.h>

#define OLED_SDA 4
#define OLED_SCL 15
#define OLED_RST 16

#define SCREEN_WIDTH 128


#define SCREEN_HEIGHT 64

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RST);

char ssid[] = " ";


char pass[] = " ";

int status = WL_IDLE_STATUS;


char servername[]=" "; // server
int port = 40000;

WiFiClient client;

// buffer to send and receive


uint16_t *frameNumber=(uint16_t *)malloc(sizeof(uint16_t));
uint16_t *fromServer=(uint16_t *)malloc(sizeof(uint16_t));

int counter;

void setup() {
Serial.begin(115200);

//reset OLED display via software


pinMode(OLED_RST, OUTPUT);
digitalWrite(OLED_RST, LOW);
delay(20);
digitalWrite(OLED_RST, HIGH);

//initialize OLED
Wire.begin(OLED_SDA, OLED_SCL);
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3c, false, false)) { // Address 0x3C for
128x32
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}

Serial.println("Attempting to connect to WPA network...");


Serial.print("SSID: ");
Serial.println(ssid);

WiFi.begin(ssid, pass);

Serial.println("");

// Wait for connection


while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());

Serial.println("\nStarting connection...");
// handshake succesful..
if (client.connect(servername, port)) {
Serial.println("connected");
}

char recvBuffer[2];
int counter=0;
while(counter<2) {
int to_read=client.available();//available permite leer datos
if(to_read>0){
for(int i=0; i<to_read; i++)
{
recvBuffer[counter]=client.read();
counter++;
}
}
}
*fromServer= *(int *) recvBuffer;

*frameNumber=(uint16_t) 1;

void readHeaders(unsigned int *bitmapSize, unsigned int *width, unsigned int *height,
unsigned char *error){

//////////////////////Recepcion de headers/////////////////////////
counter = 0;
Serial.println("going inside the while loop");
while(counter < 4) {
int to_read = client.available();

if(to_read >= 13){


Serial.println("Number of bytes recieved in server header");
Serial.println(to_read);

if (counter == 0) {
int p = 0;
char buff[4];
for (int i = 0; i < 4; i++) {
buff[i] = client.read();
}
*bitmapSize = *(uint32_t *)buff;

Serial.print("size: ");
Serial.println(*bitmapSize);
}
else if (counter == 1) {
int p = 0;
char buff[4];
for (int i = 0; i < 4; i++) {
buff[i] = client.read();
}
*width = *(uint32_t *)buff;

Serial.print("width: ");
Serial.println(*width);
}
else if (counter == 2) {
int p = 0;
char buff[4];
for (int i = 0; i < 4; i++) {
buff[i] = client.read();
}
*height = *(uint32_t *)buff;
Serial.print("height: ");
Serial.println(*height);
}
else if (counter == 3) {
*error = client.read();
Serial.print("checksum: ");
Serial.println(*error);
}
counter++;
}
}
Serial.println("out of the while loop");

unsigned char arrayXOR(unsigned char head,unsigned char* array, int length) {

unsigned char result = head;

for (int i = 0; i < length; i++) {

result = result ^ array[i];

return result;

unsigned char checksum_calc_response(unsigned char *bitmap_size, unsigned char *width,


unsigned char *height, unsigned char *bitmap) {

unsigned char result = arrayXOR(bitmap_size[0],&(bitmap_size[1]),3);


result = arrayXOR(result, width, 4);

result = arrayXOR(result, height, 4);

result = arrayXOR(result,bitmap,(*(unsigned int *) bitmap_size));

return result;

int readAndPrintBitMap(unsigned int bitmapSize, unsigned int width, unsigned int


height,unsigned char checksum){

unsigned char *newBitmap = (unsigned char *)malloc(bitmapSize);

Serial.println("asdas");

int x = 0;

while(x < bitmapSize) {


int to_read = client.available();
//Serial.print("bytes received: ");
//Serial.println(to_read);
if(to_read > 0){
Serial.println("inside if to_read > 0");

for(int j = 0; j < to_read; j++) {


//Serial.println(j);
uint8_t bite = client.read();
newBitmap[x] = bite;
x++;
}
}
}
Serial.print("bitmap size: ");
Serial.println(sizeof(newBitmap));

unsigned char checksum_response_calc = checksum_calc_response((unsigned char


*)&bitmapSize, (unsigned char *)&width, (unsigned char *)&height, (unsigned char
*)newBitmap);

Serial.printf("Checksum calculated: %d\n",checksum_response_calc);

if (checksum_response_calc == checksum) {

Serial.printf("CORRECTO\n");

//////////////////////////////////Impresion del Bitmap///////////////////////////////////////////

display.clearDisplay();
display.drawBitmap(0, 0, newBitmap, width, height, WHITE);
display.display();

delay(1000);

free(newBitmap);

return 1;

} else {
free(newBitmap);
return 0;
}

void loop() {

unsigned int *bitmapSize = (unsigned int *) malloc(4);


unsigned int *width = (unsigned int *) malloc(4);
unsigned int *height = (unsigned int *) malloc(4);
unsigned char *checksum_response = (unsigned char *) malloc(1);

Serial.printf("Requesting Frame %d\n",*frameNumber);

client.write(*frameNumber);
client.write((*frameNumber)>>8);

if (!client.connected()) {
Serial.println();
Serial.println("disconnecting.");
client.stop();

////////////////////////////////Recibiendo headers/////////////////////////////////////////////

readHeaders(bitmapSize,width,height,checksum_response);

////////////////////////////////Recepcion y impresionss bitmap/////////////////////////////////////////////

if (readAndPrintBitMap(*bitmapSize, *width, *height,*checksum_response)){

if(*frameNumber < *fromServer)


{

(*frameNumber)++;
Serial.println(*frameNumber);

}else {

*frameNumber=1;

free(bitmapSize);
free(width);
free(height);
free(checksum_response);

}
Codigo Proxy
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <dirent.h>

#include <sys/ioctl.h>
#include <net/if.h>
#include <arpa/inet.h>

#define on_error(...) { fprintf(stderr, __VA_ARGS__); fflush(stderr); exit(1); }

#define IMAGE_DIR "../PROXY-FRAMES/"


#define IMAGE_SKEL "../PROXY-FRAMES/out-frame-000.bmp"

#define SERVER_INTERFACE "enp0s3"

#define CLIENT_PORT 40000


#define CONVERSION_SERVER_PORT 40001

unsigned char arrayXOR(unsigned char head,unsigned char* array, int length) {

unsigned char result = head;

for (int i = 0; i < length; i++) {

result = result ^ array[i];

return result;

unsigned char checksum_calc_response(unsigned char *bitmap_size, unsigned char *width,


unsigned char *height, unsigned char *bitmap) {

unsigned char result = arrayXOR(bitmap_size[0],&(bitmap_size[1]),3);


result = arrayXOR(result, width, 4);

result = arrayXOR(result, height, 4);


result = arrayXOR(result,bitmap,(*(unsigned int *) bitmap_size));

return result;

int get_IP_addr(char **ip_addr) {

int fd;
struct ifreq ifr;

fd = socket(AF_INET, SOCK_DGRAM, 0);

/* I want to get an IPv4 IP address */


ifr.ifr_addr.sa_family = AF_INET;

/* I want IP address attached to "eth0" */


strncpy(ifr.ifr_name, SERVER_INTERFACE, IFNAMSIZ-1);

ioctl(fd, SIOCGIFADDR, &ifr);

close(fd);

/* display result */
printf("Server IP: %s\n", inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));

(*ip_addr) = inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr);

return 0;

int
send_all(int socket, const void *buffer, size_t length, int flags)
{

ssize_t n;
const char *p = buffer;
while (length > 0)
{
printf("Sending %ld bytes\n", length);
n = send(socket, p, length, flags);
printf("%ld bytes sent\n", n);
if (n <= 0)
return -1;
p += n;
length -= n;
}

printf("All bytes sent!\n");


return 0;
}

void count_number_of_files(uint16_t *number_of_files) {

(*number_of_files) = 0;
DIR * dirp;
struct dirent * entry;

dirp = opendir(IMAGE_DIR); /* There should be error handling after this */


while ((entry = readdir(dirp)) != NULL) {
if (entry->d_type == DT_REG) { /* If the entry is a regular file */
(*number_of_files)++;
}
}
closedir(dirp);

void number_to_char_bcd_3d(uint16_t frame_number, char *number) {

if (frame_number < 10) {

number[0] = '0';
number[1] = '0';
number[2] = (48 + frame_number);

} else if (frame_number < 100) {

number[0] = '0';
number[1] = (48 + (frame_number/10));
number[2] = (48 + (frame_number-((frame_number/10)*10)));

} else {

number[0] = (48 + (frame_number/100));


number[1] = (48 + ((frame_number-((frame_number/100)*100))/10));
number[2] = (48 + (frame_number-((frame_number/10)*10)));

int readImg(uint32_t *file_size, uint16_t frame_number, char **buffer) {


char number[3];

number_to_char_bcd_3d(frame_number,number);

char file_name[34] = IMAGE_SKEL;


file_name[26] = number[0];
file_name[27] = number[1];
file_name[28] = number[2];

file_name[34] = '\0';

printf("Trying to read file: '%s'\n",file_name);

FILE *fp = fopen(file_name,"r");


if (fp == NULL) {

printf("File '%s' not found\n", file_name);


return 1;

fseek(fp, 0L, SEEK_END);


*file_size = ftell(fp);

rewind(fp);

(*buffer) = (char *)malloc((*file_size));

fread((*buffer), 1, (*file_size), fp);

fclose(fp);

printf("Success! file size: %d\n",(*file_size));

return 0;

int main (int argc, char *argv[]) {

uint16_t *number_of_files=malloc(sizeof(uint16_t));

count_number_of_files(number_of_files);

printf("%d bmp files available.\n", (*number_of_files));

char **ip_addr = (char **)malloc(sizeof(char *));


get_IP_addr(ip_addr);

//

int proxy_server_fd, client_fd,conversion_server_fd, err;


struct sockaddr_in proxy_server, client,conversion_server;

proxy_server_fd = socket(AF_INET, SOCK_STREAM, 0);


if (proxy_server_fd < 0) on_error("Could not create proxy socket\n");

conversion_server_fd = socket(AF_INET, SOCK_STREAM, 0);

if (conversion_server_fd < 0) on_error("Could not create conversion socket\n");

proxy_server.sin_family = AF_INET;
proxy_server.sin_port = htons(CLIENT_PORT);
proxy_server.sin_addr.s_addr = htonl(INADDR_ANY);

conversion_server.sin_family = AF_INET;
conversion_server.sin_port = htons(CONVERSION_SERVER_PORT);
conversion_server.sin_addr.s_addr = inet_addr((*ip_addr));

int opt_val = 1;
setsockopt(proxy_server_fd, SOL_SOCKET, SO_REUSEADDR, &opt_val, sizeof opt_val);

err = bind(proxy_server_fd, (struct sockaddr *) &proxy_server, sizeof(proxy_server));


if (err < 0) on_error("Could not bind socket\n");

err = listen(proxy_server_fd, 128);


if (err < 0) on_error("Could not listen on proxy socket\n");

printf("Proxy server is listening on port: %d\n", CLIENT_PORT);

//Conecting to conversion server

if (connect(conversion_server_fd, (struct sockaddr *)&conversion_server ,


sizeof(conversion_server)) < 0)
{
on_error("Error connecting to conversion server\n");
}

printf("Connected to conversion server


%s:%d\n",*ip_addr,CONVERSION_SERVER_PORT);

int read;

while(1) {
socklen_t client_len = sizeof(client);
client_fd = accept(proxy_server_fd, (struct sockaddr *) &client, &client_len);
printf("Connected client\n");
if (client_fd < 0) on_error("Could not establish new connection\n");

// sending number of images available to client

err = send_all(client_fd,number_of_files,2,0);

int counter = 0;

while (1) {

// Receiving client request from client

char frame_number_buff[2];

printf("Waiting for client request\n");

while (counter < 2) {

int read = recv(client_fd, &(frame_number_buff[counter]),1,0);

if(!read) break;

if (read <0) {
on_error("Client read failed\n");
} else {

counter = counter + read;

}
}

counter = 0;

uint16_t frame_number = *(uint16_t *)frame_number_buff;

printf("Request for frame %d. \n",frame_number);

// Cliente request received

//Reading requested frame

uint32_t *file_size = malloc(sizeof(uint32_t));

char **image_buffer= (char **) (malloc(sizeof(char *)));


err = readImg(file_size, frame_number, image_buffer);

if (err == 1) {

printf("Error, file not found aborting\n");


exit(1);

// Requested frame read

// Requesting to conversion server

uint8_t error_val = 1;

while (error_val != 0) {

printf("Sending header\n");

err = send_all(conversion_server_fd,(file_size),4,0);

printf("Sending BMP file \n");

err = send_all(conversion_server_fd,(*image_buffer),(*file_size),0);

//Receiving conversion server response

//Receiving header bitmap size

char bitmap_size_buffer[4];
counter = 0;

while (counter < 4) {

int read = recv(conversion_server_fd, &(bitmap_size_buffer[counter]),1,0);

if(!read) break;

if (read <0) {

on_error("Conversion read failed\n");

} else {

counter = counter + read;

}
}

counter = 0;

uint32_t bitmap_size = *(uint32_t *)bitmap_size_buffer;

printf("Bitmap size received: %d \n", bitmap_size);

//Receive image width

char img_width_buff[4];

while (counter < 4) {

int read = recv(conversion_server_fd, &(img_width_buff[counter]),1,0);

if(!read) break;

if (read <0) {
on_error("Conversion server read failed\n");
} else {

counter = counter + read;

}
}

counter = 0;

uint32_t img_width = *(uint32_t *)img_width_buff;

printf("Image width: %d. \n",img_width);

//Receive image height

char img_height_buff[4];

while (counter < 4) {

int read = recv(conversion_server_fd, &(img_height_buff[counter]),1,0);

if(!read) break;

if (read <0) {
on_error("Client read failed\n");
} else {
counter = counter + read;

}
}

counter = 0;

uint32_t img_height = *(uint32_t *)img_height_buff;

printf("Image height: %d. \n",img_height);

//Image size value

//uint16_t img_size = (img_height * img_width)/8;


//printf("Image size: %d. \n",img_size);

//Receive checksum

unsigned char checksum_buff;


counter = 0;

while (counter < 1) {

int read = recv(conversion_server_fd, &(checksum_buff),1,0);

if(!read) break;

if (read <0) {
on_error("Client read failed\n");
} else {

counter = counter + read;

}
}

counter = 0;

//Receive image

char bitmap_buff[bitmap_size];

while (counter < bitmap_size) {

int read = recv(conversion_server_fd, &(bitmap_buff[counter]),1,0);

if(!read) break;
if (read <0) {
on_error("Client read failed\n");
} else {

counter = counter + read;

}
}

printf("Image received.\n");

unsigned char checksum_received = checksum_calc_response((unsigned char


*)&bitmap_size, (unsigned char *)&img_width, (unsigned char *)&img_height, (unsigned char
*)bitmap_buff);

printf("checksum calculated: %d, checksum received: %d


\n",checksum_received,checksum_buff);

if (checksum_received != checksum_buff) {

printf("Error received, repeating request\n");

} else {

error_val = 0;

printf("No error, forwarding to client\n");

printf("Sending bitmap size: %d\n", bitmap_size);


send_all(client_fd,&(bitmap_size),4,0);
printf("Sending image width size: %d\n", img_width);
send_all(client_fd,&(img_width),4,0);
printf("Sending image height size: %d\n", img_height);
send_all(client_fd,&(img_height),4,0);
printf("Sending error byte: %d\n", error_val);
send_all(client_fd,&(checksum_received),1,0);

send_all(client_fd,bitmap_buff,bitmap_size,0);

free(file_size);
free(*image_buffer);
free(image_buffer);
counter = 0;

//

//printf("First byte: %X, last byte: %X\n",(*image_buffer)[0],(*image_buffer)[1086]);

//FILE *f_dst = fopen("dest.bmp", "w");

//fwrite((*image_buffer),1,(*file_size),f_dst);

//fclose(f_dst);

}
Codigo convertidor
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <math.h>

#define on_error(...) {fprintf(stderr,__VA_ARGS__); fflush(stderr); exit(1);}


#define C_PORT 40001
int bin_to_num(int valor[]);

void num_to_bin(int num,int valor[]);

unsigned char arrayXOR(unsigned char head,unsigned char* array, int length) {

unsigned char result = head;

for (int i = 0; i < length; i++) {

result = result ^ array[i];

return result;
}

unsigned char checksum_calc(unsigned char *bitmap_size, unsigned char *width, unsigned


char *height, unsigned char *bitmap) {

unsigned char result = arrayXOR(bitmap_size[0],&(bitmap_size[1]),3);


result = arrayXOR(result, width, 4);

result = arrayXOR(result, height, 4);

result = arrayXOR(result,bitmap,(*(unsigned int *) bitmap_size));

return result;

int
send_all(int socket, const void *buffer, size_t length, int flags)
{
ssize_t n;
const char *p = buffer;
while (length > 0)
{
n = send(socket, p, length, flags);
if (n <= 0)
return -1;
p += n;
length -= n;
}
return 0;
}

int bits_nc(uint32_t ancho)


{
int resultado=0;
resultado=ancho%8;
return resultado;

}
int valoredondeado(uint32_t ancho)
{

int resultado=0;
double aux_result;
double width=(double) ancho;
aux_result=width/8;

resultado= ceil(aux_result);
return resultado;
}
int modulo4(uint32_t ancho)
{
int resultado=0;
int counter4=0;
double aux_result=0;
double width=(double) ancho;
aux_result=width/8;

resultado= ceil(aux_result);

while(counter4<resultado)
{
counter4=counter4+4;

if(counter4>resultado)
{return counter4;}
}

}
void final(int rounded,char vv[],int bits_ncc,uint32_t ancho,char vector_final[],int sizeT)
{
int resultado=0;
resultado=bits_nc(ancho);
if(resultado==0)
{
for(int ccc=0;ccc<sizeT;ccc++)
{
vector_final[ccc]=vv[ccc];

}
}else
{
int temp[8];
int temp2[8];
int numeronuevo=0;
int contador=7;
int contador2=0;
num_to_bin(vv[rounded-1],temp);

while(contador>=0)
{
if(contador>7-bits_ncc)
{
temp2[contador]=temp[contador];
}else
{
temp2[contador]=0;
}
contador=contador-1;
}
numeronuevo=bin_to_num(temp2);

printf("nuevo NUmero %d\n",numeronuevo);


for(int jj=0;jj<sizeT;jj++)
{
vector_final[jj]=vv[jj];

}
for(int ii=rounded-1;ii<sizeT;ii=ii+rounded)
{
vector_final[ii]=numeronuevo;
}

}
}
void colores(char vec_read[],int size,uint8_t blanco,uint8_t negro,char vec_colores[])
{
if((blanco==255) && (negro==0))
{
printf("BLANCO:1,INVERSION\n");
printf("NEGRO:0\n");

for(int con=0;con<size;con++)
{
vec_colores[con]=255-vec_read[con];
}
}else if((blanco==0) && (negro==255))
{
printf("BLANCO:0,SIN INVERSION\n");
printf("NEGRO:1\n");

for(int con=0;con<size;con++)
{
vec_colores[con]=vec_read[con];
}
}
}
void indice(int size_of_row,int size,int rounded,int *total)
{
int contador_p=0;

for(int c=size-1;c>=0;c=c-size_of_row)
{

contador_p=contador_p+1;
}
*total=size-contador_p*(size_of_row-rounded);
}
void mostrar(char vect[],int tam)
{
for(int con=0;con<tam;con++)
{
printf("Valor [%d] : %#02x\n",con,vect[con]);
}
}
void ordenar(char vector[],int size_of_row,int size,int rounded, char ordenada[])
{
int contador_p=0;
int total=0;
int inicio1=size-1;
int counter1=size_of_row;

int counter3=0;
int counter4=0;
int counter5=0;
for(int c=size-1;c>=0;c=c-size_of_row)
{

contador_p=contador_p+1;
}
total=size-contador_p*(size_of_row-rounded);
char vec[total];
counter3=inicio1-(size_of_row-rounded)-rounded;
counter5=counter3;

for(int i=0;i<total;i++)
{
counter3=counter3+1;
vec[i]=vector[counter3];

counter4=counter4+1;
if(counter4==rounded)
{
counter5=counter5-(size_of_row-rounded)-rounded;
counter3=counter5;
counter4=0;
}
}

for(int j=0;j<total;j++)
{
ordenada[j]=vec[j];
}

}
void num_to_bin(int num,int valor[])
{
int aux=0;
for(int c=7;c>=0;c--)
{
aux=num>>c;
if(aux & 1)
valor[c]=1;
else
valor[c]=0;
}

int bin_to_num(int valor[])


{
int res=0;
for(int j=0;j<=7;j++)
{
if(valor[j]==1)
{
res=res+pow(2,j);
}

return res;

void valor_header(int i_header,int f_header,char data_to_a[],int size,char result[],int flag)


{

char v1[size];
char v2[sizeof(v1)];

for(int c1=i_header;c1<=f_header;c1++)
{
v1[c1-i_header]=data_to_a[c1];

}
//inversion

for(int c2=sizeof(v1)-1;c2>=0 ;c2--)


{
v2[sizeof(v1)-1-c2]=v1[c2];

if(flag==1)// inversion
{
for(int ii=0;ii<=size;ii++)
{
result[ii]=v1[ii];

}
} else
{
for(int iii=0;iii<=size;iii++)
{
result[iii]=v2[iii];

}
}

}
uint32_t shift(char vector[],int size)
{
uint32_t resultado=0;
int counter=0;
for(int c=size-1;c>=0;c--)
{
resultado=resultado | (vector[c]<<counter);
counter+=8;
}
counter=0;
return resultado;
resultado=0;

}
int main(int argc,char *argv[])
{
int conversor_fd,proxy_fd,err;
struct sockaddr_in conversion_server,proxy;

conversor_fd=socket(AF_INET,SOCK_STREAM,0);
if(conversor_fd<0) on_error("Could not create socket\n");

conversion_server.sin_family=AF_INET;
conversion_server.sin_port=htons(C_PORT);
conversion_server.sin_addr.s_addr=htonl(INADDR_ANY);

int opt_val=1;
setsockopt(conversor_fd,SOL_SOCKET,SO_REUSEADDR,&opt_val,sizeof opt_val);

err=bind(conversor_fd,(struct sockaddr*) &conversion_server,sizeof(conversion_server));


if(err<0)on_error("could not bind socket\n");
err=listen(conversor_fd,128);

if(err<0) on_error("Could not listen on socket\n");


printf("Server ins listening on %d\n",C_PORT);
//rx of size
char data_to_send[4];
int lecturas=0;
int header_size;
int counter2=0;
int read;
int read_header;
int counter=0;
int counter3=0;

int counter_e=0;
int flag_e;

socklen_t proxy_len=sizeof(proxy);
proxy_fd=accept(conversor_fd,(struct sockaddr *) &proxy,&proxy_len);
printf("Connected to proxy\n");
if(proxy_fd<0) on_error("New connection failed\n");

while(1)
{
//socklen_t proxy_len=sizeof(proxy);
//proxy_fd=accept(conversor_fd,(struct sockaddr *) &proxy,&proxy_len);
//printf("Connected to proxy\n");
//if(proxy_fd<0) on_error("New connection failed\n");

int BUFFER_SIZE_H=4;
char buffer_header[BUFFER_SIZE_H];
while(counter2!=1)
{
while(lecturas<4)
{
read_header=recv(proxy_fd,&(buffer_header[lecturas]),4,0);
lecturas=lecturas+read_header;

}
uint32_t header_s = *(uint32_t *)buffer_header;
int header_size= (int)header_s;
printf("SIze: %d\n",header_s);
printf("SIze: %d\n",header_size);

//lectura data

int BUFFER_SIZE=header_size;

char buffer_data[BUFFER_SIZE];

while(counter3< header_size)
{
read=recv(proxy_fd,&(buffer_data[counter3]),header_size,0);

if(read<0)
{
on_error("Proxy write failed\n");
}
else {

counter3=counter3+read;
}
buffer_data[header_size]='\0';
}

char aux[header_size];
for(int ii=0;ii<=sizeof(aux);ii++)
{

aux[ii]=buffer_data[ii];
printf("valor bmp rx [%d] : %#02x\n",ii,aux[ii]);

FILE *fp;

printf("\nARCHIVO BMP RECIBIDO CORRECTAMENTE\n");


fp=fopen("archivo.bmp", "w");
fwrite(&aux,sizeof(char),header_size,fp);
fclose(fp);

char size_total[4];
char inicio_data[4];
char width[4];
char height[4];
char size_bm[4];
char paletab[4];
char paletan[4];

printf("\n DATOS DEL BITMAP \n");


//sizetotal
uint32_t sst=0;

valor_header(2,5,aux,4,size_total,0);
sst=shift(size_total,sizeof(size_total));
printf("SIZE TOTAL: %d\n",sst);

//Ancho
uint32_t at=0;
valor_header(18,21,aux,4,width,0);
at=shift(width,sizeof(width));
printf("WIDTH: %d\n",at);

//alto
uint32_t ht=0;
valor_header(22,25,aux,4,height,0);
ht=shift(height,sizeof(height));
printf("HEIGHT: %d\n",ht);
//inicio de data

uint32_t id;
valor_header(10,13,aux,4,inicio_data,0);
id=shift(inicio_data,sizeof(inicio_data));
printf("INICIO POS: %d\n",id);
//paleta de colores
uint8_t pt_b=0;
uint8_t negro=0;
valor_header(54,57,aux,4,paletab,0);
valor_header(58,61,aux,4,paletan,0);
//mostrar(paletab,sizeof(paletab));
// mostrar(paletan,sizeof(paletan));
pt_b=shift(paletab,sizeof(paletab));
negro=shift(paletan,sizeof(paletan));
printf("PALETA B : %d\n",pt_b);
printf("PALETA N : %d\n",negro);
//size de bitmap

uint32_t smp=0;
valor_header(34,37,aux,4,size_bm,0);
smp=shift(size_bm,sizeof(size_bm));
printf("SIZE BMP: %d\n",smp);
//size bitmap
char data_to_send[smp];
valor_header(62,header_size,aux,smp,data_to_send,1);
printf("\n DATA BITMAP \n");

//tamano de fila
int sizeFila=0;
int bits_n=0;
sizeFila=modulo4(at);
bits_n=bits_nc(at);
printf("SIZE OF ROW: %d\n",sizeFila);
printf("BITS TOMADOS: %d\n",bits_n);

// dta envio
int vr=0;
// int tot;
int size1=0;
vr=valoredondeado(at);
indice(sizeFila,sizeof(data_to_send),vr,&size1);
char ordenada[size1];
char var_color[size1];
char vector_f[size1];
ordenar(data_to_send,sizeFila,sizeof(data_to_send),vr,ordenada);
// mostrar(ordenada,size1);
colores(ordenada,sizeof(ordenada),pt_b,negro,var_color);
// mostrar(var_color,sizeof(var_color));
final(vr,var_color,bits_n,at,vector_f,size1);
printf("\nDATA A ENVIAR BITMAP\n");

mostrar(vector_f,sizeof(vector_f));

unsigned char checksum = checksum_calc((unsigned char *)&size1, (unsigned char


*)&at, (unsigned char *)&ht, (unsigned char *)vector_f);
//enviando datos al proxy
err=send_all(proxy_fd,&size1,4,0);//total bitmap
err=send_all(proxy_fd,&at,4,0);//ancho
err=send_all(proxy_fd,&ht,4,0);//alto
err=send_all(proxy_fd,&checksum,1,0);//checksum
err=send_all(proxy_fd,vector_f,size1,0);//data bitmap
printf("DATOS ENVIADOS CORRECTAMENTE..\n");
counter2=counter2+1;

}//fin while(counter2)

counter2=0;
counter3=0;
lecturas=0;

//shutdown(proxy_fd,SHUT_RDWR);
//close(proxy_fd);

}//finn while 1

También podría gustarte