-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparoYEspera.cpp
More file actions
429 lines (372 loc) · 16 KB
/
paroYEspera.cpp
File metadata and controls
429 lines (372 loc) · 16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
#include "paroYEspera.h"
using namespace std;
void ImprimirMenuParoEsperaMaestro(){
cout << "Seleccione el tipo de operacion: " << endl;
cout << "[1] Operacion seleccion. " << endl;
cout << "[2] Operacion sondeo. " << endl;
cout << "[3] Salir. " << endl
<< endl;
}
bool MaestroParoYEspera(interface_t *interfaz, unsigned char mac_origen[6], unsigned char mac_destino[6], unsigned char tipo[2])
{
// MENU SELECCION PAROYESPERA - MAESTRO
ImprimirMenuParoEsperaMaestro();
// INPUT DEL USUARIO
unsigned char teclaPulsada = getch();
if (teclaPulsada == '1') // MODO SELECCION MAESTRO
{
cout << "PULSADO : 1 - Iniciando protocolo de seleccion..." << endl;
MaestroSeleccion(interfaz, mac_origen, mac_destino, tipo);
}
else if (teclaPulsada == '2') // MODO SONDEO MAESTRO
{
cout << "PULSADO : 2 - Iniciando protocolo de sondeo..." << endl;
MaestroSondeo(interfaz, mac_origen, mac_destino, tipo);
}
else if (teclaPulsada == '3') // SALIR
{
cout << "Saliendo de Paro y Espera..." << endl;
return true;
}
else
cout << "TECLA INVALIDA" << endl; // BREAK O ALGO ASI
return false;
}
// INVIERTE EL VALOR DE NUMEROTRAMA PASADO POR PARAMETROS
// SI ES 0 LO ACTUALIZA A 1
// SI ES 1 LO ACTUALIZA A 0
void SwapNumeroTrama(unsigned char &numeroTrama)
{
if (numeroTrama == '1'){
numeroTrama = '0';
}
else if (numeroTrama == '0'){
numeroTrama = '1';
}
else cout << endl << " #### ERROR, NUMERO DE TRAMA INCORRECTO ####" << endl;
}
void MaestroSeleccion(interface_t *interfaz, unsigned char mac_origen[6], unsigned char mac_destino[6], unsigned char tipo[2])
{
unsigned char direccion = 'R'; // El valor de Dirección será ‘R’ operación de Selección - 'T' operación de Sondeo
unsigned char control = 5; // Al principio enviamos una trama ENQ para saber si el esclavo esta listo
// • Trama de control ENQ: Valor 05.
// • Trama de control EOT: Valor 04.
// • Trama de control ACK: Valor 06.
// • Trama de control NACK: Valor 21.
// • Trama de datos - STX: Valor 02.
unsigned char numeroTrama = '0'; // oscilará entre los valores ‘0’ y ‘1’ (como carácter, no int ni nada raro)
// Enviamos la trama de control /* DIRECCION // CONTROL // NUMERO DE TRAMA */
EnviarTramaControl(interfaz, mac_origen, mac_destino, tipo, direccion, control, numeroTrama);
// Mostramos la trama enviada por pantalla (POR ESO LA 'E') LA RECIBIDA MOSTRARA 'R'
MostrarTrama('E', direccion, control, numeroTrama, ' ');
// Seguimos recibiendo tramas de control
RecibirTramaControl(interfaz, direccion, control, numeroTrama);
// Cuando recibamos una trama de control con valor control 6 (ACK), la mostramos con una 'R', de recibida:
// RECORDAMOS QUE ACK ES LA TRAMA DE CONFIRMACION, LA TRAMA ENVIADA HA SIDO RECIBIDA
if (control == 6)
{
MostrarTrama('R', direccion, control, numeroTrama, ' ');
cout << endl;
}
// Envio de fichero en Paro y espera (SOLO MAESTRO)
EnviarFicheroParoyEspera(interfaz, mac_origen, mac_destino, tipo, direccion, control, numeroTrama);
// Envio de la trama 'EOT' para indicar fin de envio
EnviarTramaControl(interfaz, mac_origen, mac_destino, tipo, direccion, 4, '0');
MostrarTrama('E', direccion, 4, numeroTrama, ' ');
// Seguimos recibiendo tramas de control
RecibirTramaControl(interfaz, direccion, control, numeroTrama);
// Cuando recibamos una trama de control con valor control 6, la mostramos con una 'R', de recibida:
if (control == 6)
{
MostrarTrama('R', direccion, control, numeroTrama, ' ');
}
cout << "Fin de Seleccion por parte del Maestro" << endl
<< endl;
}
void EsclavoSeleccion(interface_t *interfaz, unsigned char mac_origen[6], unsigned char mac_destino[6], unsigned char tipo[2], unsigned char direccion, unsigned char control, unsigned char numeroTrama)
{
// EN ESTE FICHERO ESCRIBIREMOS LAS TRAMAS RECIBIDAS
ofstream outputStream;
outputStream.open("RProtoc.txt");
// BUFFERED READER:
char cadena[254];
unsigned char longitud;
// ENVIO LA TRAMA DE RESPUESTA CORRECTA(ACK) - codigo 6 PARA ESTABLECER EL PROTOCOLO DE SELECCION
EnviarTramaControl(interfaz, mac_origen, mac_destino, tipo, direccion, 6, numeroTrama);
MostrarTrama('E', direccion, 6, numeroTrama, ' ');
cout << endl;
bool fin = false;
while (!fin && control != 4)
{
RecibirTramaParoyEspera(interfaz, direccion, control, numeroTrama, cadena, longitud);
if (control == 4)
{
cout << endl;
MostrarTrama('R', direccion, control, numeroTrama, ' ');
control = 6;
fin = true;
}
else
{
if (longitud != 0 && outputStream.is_open())
{
outputStream.write(cadena, longitud); // ESCRIBIMOS EN EL FICHERO LA TRAMA RECIBIDA
control = 6;
}
else
{
control = 21;
}
}
EnviarTramaControl(interfaz, mac_origen, mac_destino, tipo, direccion, control, numeroTrama);
MostrarTrama('E', direccion, control, numeroTrama, ' ');
}
outputStream.close();
cout << "Fin de Seleccion por parte del Esclavo." << endl;
cout << "Presione ESC para finalizar..." << endl;
}
// Recibe las tramas de control que envia el maestro
bool EsclavoParoYEspera(interface_t *interfaz, unsigned char mac_origen[6], unsigned char mac_destino[6], unsigned char tipo[2])
{
cout << "Estas en modo esclavo" << endl;
// INICIALIZAMOS VARIABLES QUE SERAN ASIGNADAS LLAMANDO A LOS METODOS (SON INPUT / OUTPUT):
unsigned char direccion;
unsigned char control;
unsigned char numeroTrama;
RecibirTramaControl(interfaz, direccion, control, numeroTrama);
if (direccion == 'R')
{ // SI RECIBE UNA R ES PROTOCOLO SELECCION
MostrarTrama('R', direccion, control, numeroTrama, ' ');
EsclavoSeleccion(interfaz, mac_origen, mac_destino, tipo, direccion, control, numeroTrama);
}
if (direccion == 'T')
{ // SI RECIBE UNA 'T' ES PROTOCOLO SONDEO
MostrarTrama('R', direccion, control, numeroTrama, ' ');
EsclavoSondeo(interfaz, mac_origen, mac_destino, tipo, direccion, control, numeroTrama);
}
return true;
}
void EnviarTramaControl(interface_t *interfaz, unsigned char mac_origen[6], unsigned char mac_destino[6], unsigned char tipo[2], unsigned char direccion, unsigned char control, unsigned char numeroTrama)
{
// Las tramas de control contendrán 3 valores diferenciados: direccion, control y numeroTrama.
// Los enviamos juntos en un Array:
unsigned char datosTramaControl[3] = {
direccion,
control,
numeroTrama};
// Construimos la trama
unsigned char *tramaEnviada = BuildFrame(mac_origen, mac_destino, tipo, datosTramaControl);
// Enviamos la trama, que tendra un tamaño de 3 bytes (DIRECCION, CONTROL Y NUMEROTRAMA)
SendFrame(interfaz, tramaEnviada, 3);
// liberamos memoria de la trama que hemos enviado
free(tramaEnviada);
}
// BCE SOLO NECESARIO PARA TRAMAS DE DATOS, SI NO ES DE DATOS BCE = ' '
void MostrarTrama(unsigned char tipo, unsigned char direccion, unsigned char control, unsigned char numeroTrama, char BCE)
{
if (control == 2) // TRAMAS DE DATOS - STX
{
cout << tipo << " " << direccion << " "
<< "STX " << numeroTrama;
// imprimir el BCE
printf(" %d", BCE);
}
else // TRAMAS DE CONTROL
{
cout << tipo << " " << direccion << " "; // Si la trama es enviada, tipo = 'E', si es Recibida, tipo = 'R'
switch (control)
{
case 4:
cout << "EOT " << numeroTrama << endl;
break;
case 5:
cout << "ENQ " << numeroTrama << endl;
break;
case 6:
cout << "ACK " << numeroTrama << endl;
break;
case 21:
cout << "NACK " << numeroTrama << endl;
break;
default:
// cout << "EOT " << numeroTrama << endl;
cout << " ### ERROR LA TRAMA NO POSEE UN VALOR DE CONTROL CORRECTO ### " << endl;
break;
}
}
}
void RecibirTramaControl(interface_t *interfaz, unsigned char &direccion, unsigned char &control, unsigned char &numeroTrama)
{
bool recibida = false;
while (!recibida)
{
// Esperamos a recibir una trama de control
apacket_t trama = ReceiveFrame(interfaz);
if (trama.packet != NULL)
{
recibida = true;
// if (trama.packet[12] == 0x88 && trama.packet[13] == 0x08){ // NO HACE FALTA COMPROBAR
// Extraemos la direccion, control y numero de trama de la trama recibida, y actualizamos los valores input-output
direccion = trama.packet[14]; // DIRECCION EN EL BYTE 14 DEL PAQUETE RECIBIDO
control = trama.packet[15]; // CONTROL EN EL BYTE 15 ''
numeroTrama = trama.packet[16]; // NUMERO TRAMA (0) O (1) EN EL BYTE 16
}
}
}
// ENVIA LA TRAMA DE DATOS O STX
void EnviarTramaDatos(interface_t *interfaz, unsigned char mac_origen[6], unsigned char mac_destino[6], unsigned char tipo[2], unsigned char direccion, unsigned char control, unsigned char numeroTrama, unsigned char longitud, unsigned char cadena[], unsigned char BCE)
{
unsigned char datos[259]; // PAQUETE DE 259 BYTES
datos[0] = direccion;
datos[1] = control;
datos[2] = numeroTrama;
datos[3] = longitud;
int j = 0;
for (int i = 0; i < longitud; i++)
{
datos[4 + i] = cadena[i];
j++;
}
datos[4 + j] = BCE; // AÑADIMOS EL BCE A LA TRAMA
// CONSTRUIMOS Y ENVIAMOS LA TRAMA:
unsigned char *trama = BuildFrame(mac_origen, mac_destino, tipo, datos);
SendFrame(interfaz, trama, longitud + 5);
free(trama);
MostrarTrama('E', direccion, control, numeroTrama, BCE);
cout << endl;
}
// Comprueba si se ha pulsado la tecla F4 = '27 + O + S'
// Si se ha pulsado F4, cont I/O se incrementa. Usaremos este metodo para introducir errores pulsando F4 durante el protocolo
void ComprobarPulsacionF4(int &cont)
{
unsigned char teclaPulsada;
if (kbhit())
{
teclaPulsada = getch();
if (teclaPulsada == 27)
{
teclaPulsada = getch();
if (teclaPulsada == 'O')
{
teclaPulsada = getch();
if (teclaPulsada == 'S')
{
__fpurge(stdin);
cont++;
}
}
}
}
}
// ENVIA EL FICHERO "EProtoc.txt" POR PARO Y ESPERA
void EnviarFicheroParoyEspera(interface_t *interfaz, unsigned char mac_origen[6], unsigned char mac_destino[6], unsigned char tipo[2], unsigned char direccion, unsigned char control, unsigned char numeroTrama)
{
__fpurge(stdin); // limpiamos el input de teclado
ifstream flujoLectura("EProtoc.txt"); // introduce aquí el archivo y la ruta del fichero que deseas enviar
char cadena[254]; // cadena a leer
unsigned char numeroTramaRecibida;
numeroTramaRecibida = ' ';
int longitudCadena; // longitud de la trama a enviar (sirve para calcular BCE)
// INTRODUCCION DE ERRORES AL PULSAR F4 - VERSION 5
unsigned char correccion; // variable auxiliar para corregir la trama enviada
int numErrores = 0; // cuenta el numero de errores introducidos
if (flujoLectura.is_open())
{
while (!flujoLectura.eof())
{
// LEEMOS DE FICHERO
flujoLectura.read(cadena, 254);
longitudCadena = flujoLectura.gcount();
unsigned char BCE = CalculoBCE(longitudCadena, cadena);
control = 2; // NUMERO PARA STX ESTAMOS ENVIANDO TRAMAS DE DATOS
// SI SE HA PULSADO F4, INCREMENTO numErrores
ComprobarPulsacionF4(numErrores);
// Introducimos el error si se ha pulsado F4 durante el protocolo
if (numErrores != 0)
{
correccion = cadena[0]; // Guardamos aqui el dato correcto para luego
cadena[0] = 184; // Introducimos el caracter especial (Error)
numErrores--; // DECREMENTAMOS EL NUMERO DE ERRORES A INTRODUCIR
cout << "INTRODUCIENDO ERROR..." << endl;
}
// Enviamos la trama de datos (QUE AHORA PUEDE CONTENER ERRORES)
EnviarTramaDatos(interfaz, mac_origen, mac_destino, tipo, direccion, control, numeroTrama, longitudCadena, (unsigned char *)cadena, BCE);
// Esperamos a recibir la trama de respuesta del esclavo:
// ACK -> CONTROL == 6
while (control != 6 || numeroTrama != numeroTramaRecibida)
{
RecibirTramaControl(interfaz, direccion, control, numeroTramaRecibida);
// TODO VERSION 5 INTRODUCCION DE ERROES
if (control == 21) // 21: Trama NACK - ERROR
{ // Si envian una trama NACK, corregimos los datos y los enviamos de nuevo TODO VERSION 5
control = 2; // LA TRAMA CORREGIDA VUELVE A SER DE DATOS
cadena[0] = correccion;
MostrarTrama('R', direccion, control, numeroTrama, ' ');
cout << endl;
// ENVIAMOS LA RESPUESTA, AHORA CORREGIDA:
EnviarTramaDatos(interfaz, mac_origen, mac_destino, tipo, direccion, control, numeroTrama, longitudCadena, (unsigned char *)cadena, BCE);
MostrarTrama('E', direccion, control, numeroTrama, ' ');
cout << endl;
}
}
// Mostramos la trama de respuesta del esclavo:
MostrarTrama('R', direccion, control, numeroTrama, ' ');
// INVERTIMOS VALORES DE numeroTrama PARA EL SIGUIENTE ENVIO
SwapNumeroTrama(numeroTrama);
}
}
else
{
cout << " #### ERROR AL ABRIR EL FICHERO #### " << endl;
}
cout << endl;
flujoLectura.close();
}
// Para calcular el valor del BCE de una trama se debe hacer la operación lógica XOR
// dos a dos entre todos los caracteres de los datos correspondiente al contenido del fichero.
char CalculoBCE(int longitudCadena, char cadena[])
{
if (longitudCadena > 0) // Siempre debe ser mayor que 0
{
char BCE;
BCE = cadena[0]; // inicializamos al primer valor (0)
for (int i = 1; i < longitudCadena; i++)
{
BCE = BCE xor cadena[i];
}
return BCE;
}
else
return 0; // Error
}
void RecibirTramaParoyEspera(interface_t *interfaz, unsigned char &direccion, unsigned char &control, unsigned char &numeroTrama, char cadena[], unsigned char &longitud)
{
bool tramaRecibida = false;
while (!tramaRecibida)
{
apacket_t trama = ReceiveFrame(interfaz);
if (trama.packet != NULL)
{
direccion = trama.packet[14];
control = trama.packet[15];
numeroTrama = trama.packet[16];
tramaRecibida = true;
if (control == 2)
{
longitud = trama.packet[17];
for (int i = 0; i < longitud; i++)
{
cadena[i] = trama.packet[18 + i];
}
unsigned char BCERecibido = trama.packet[18 + longitud];
unsigned char BCECalculado = CalculoBCE(longitud, cadena); // SERA EL BCE QUE CALCULE EL ESCLAVO Y RESPONDERA AFIRMATIVO SI ES IGUAL
if (BCECalculado != BCERecibido)
{
longitud = 0; // reseteamos la longitud de la cadena si no coinciden (ERROR)
}
MostrarTrama('R', direccion, control, numeroTrama, BCERecibido);
printf(" %d\n", BCECalculado); // A CONTINUACION MOSTRAMOS EL BCE calculado por el esclavo para comparar
}
}
}
}