#include <stdlib.h>
#include <iostream>
#include <time.h>
#include <sstream>
#include <string>
#include <L2capChannel.h>
using namespace std;
L2capChannel::L2capChannel (int CID, int PSM, Socket* a) // Constructor
{
_estado = CLOSED;
_localCID = CID;
_PSM = PSM;
sockCanal = a;
std::string cad = "080001000305040001004000";
sockCanal->SendBytes(cad); // No escribe, no se por que
}
L2capChannel::L2capChannel (int CID, int PSM,void* a, void(*pt2Func)(void*, std::string))
{
_estado = CLOSED;
_localCID = CID;
_PSM = PSM;
_ME = a;
cout<<"Se supone que enviamos!"<<endl;
pt2Func (_ME,"080001000205040001004000"); // Llama al Wrapper y éste deberia escribir, pero no lo hace
// _ME->sendRaw(); // deberia poder mandar asi tambien, pero no
}
L2capChannel::~L2capChannel () // Constructor
{
}
void L2capChannel::imprimeArray (Tpdu_L2CAP datain, unsigned int longitud)
{
unsigned int i;
printf(" \n\n El array de datos es el siguiente: \n \n");
for (i=0; i<(longitud); i++)
{
printf("%X ",*(datain+i));
}
printf(" \n \n");
}
void L2capChannel::escribeL2CAPcon_req_TX ()
{
L2CAPcon_req_TX.Code = L2CAP_CONREQ;
L2CAPcon_req_TX.ID = _identifier;
L2CAPcon_req_TX.Length = 4;
L2CAPcon_req_TX.PSM = _PSM;
L2CAPcon_req_TX.SCID = _localCID;
}
void L2capChannel::escribeL2CAPcon_res_TX (int result)
{
L2CAPcon_res_TX.Code = L2CAP_CONRES;
L2CAPcon_res_TX.ID = L2CAPcon_req_RX.ID;
L2CAPcon_res_TX.Length = 6;
L2CAPcon_res_TX.DCID = _localCID;
L2CAPcon_res_TX.SCID = _remoteCID;
L2CAPcon_res_TX.Result = result;
L2CAPcon_res_TX.Status = 0x0000;
}
void L2capChannel::leerL2CAPcon_req(Tpdu_L2CAP datain, unsigned int &n)
{
L2CAPcon_req_RX.Code = *(datain + n);
L2CAPcon_req_RX.ID = *(datain + n+1);
L2CAPcon_req_RX.Length = *(datain + n+2) + (*(datain+n+3))*256;
L2CAPcon_req_RX.PSM = *(datain + n+4) + (*(datain+n+5))*256;
L2CAPcon_req_RX.SCID = *(datain + n+6) + (*(datain+n+7))*256;
int _remoteCID = L2CAPcon_req_RX.SCID;
n += (L2CAPcon_req_RX.Length + 4);
cout<<"vamos por aqui"<<endl;
if (_estado==CLOSED)
{
unsigned int result=0; //successfull
if (result==0)
{
escribeL2CAPcon_res_TX (result);
_estado=WAIT_CONFIG;
}
else if (result==1) //pending
{
escribeL2CAPcon_res_TX (result);
_estado=WAIT_CONNECT;
}
else //No puede
{
escribeL2CAPcon_res_TX (result);
}
sendComando(L2CAP_CONRES);
}
} // leerL2CAPcon_req
int L2capChannel::leerL2CAPcon_res(Tpdu_L2CAP datain, unsigned int &n)
{
unsigned int _receivedIdentifier = *(datain + n+1);
switch (_estado)
{
case WAIT_CONNECT_RSP:
{
if (L2CAPcon_req_RX.ID !=_receivedIdentifier)
{
cout<<"Identificador no se corresponde con el esperado."<<endl;
return 2;
}
L2CAPcon_res_RX.Code = *(datain + n); // Code = 03
L2CAPcon_res_RX.ID = *(datain + n+1);
L2CAPcon_res_RX.Length = *(datain + n+2) + (*(datain+n+3))*256;
L2CAPcon_res_RX.DCID = *(datain + n+4) + (*(datain+n+5))*256;
L2CAPcon_res_RX.SCID = *(datain + n+6) + (*(datain+n+7))*256;
L2CAPcon_res_RX.Result = *(datain + n+8) + (*(datain+n+9))*256;
L2CAPcon_res_RX.Status = *(datain + n+10) + (*(datain+n+11))*256;
n += (L2CAPcon_res_RX.Length + 4);
switch (L2CAPcon_res_RX.Result)
{
case 0: //Success
{
_estado = WAIT_CONFIG;
_remoteCID = L2CAPcon_res_RX.DCID;
break;
}
case 1: //pending
{
break;
}
case 2: //Refused
{
_estado = CLOSED;
cout<<"PSM not supported."<<endl;
return -1;
break;
}
case 3: //Refused
{
_estado = CLOSED;
cout<<"Security block."<<endl;
return -1;
break;
}
case 4: //Refused
{
_estado = CLOSED;
cout<<"No resources available."<<endl;
return -1;
break;
}
default:
{
}
}
return 0;
break;
}
default :
{
return 1;
}
}
}
void L2capChannel::imprimeComando (unsigned int codigo)
{
unsigned int i;
switch (codigo)
{
case L2CAP_CONREQ :
{
printf("\n \n*****Connection Request******* \n");
printf("El campo Code es de valor %X \n",L2CAPcon_req_RX.Code);
printf("El campo ID es de valor %X \n",L2CAPcon_req_RX.ID);
printf("El campo Length es de valor %X \n",L2CAPcon_req_RX.Length);
printf("El campo PSM es de valor %X \n",L2CAPcon_req_RX.PSM);
printf("El campo SCID es de valor %X \n \n",L2CAPcon_req_RX.SCID);
break;
}
case L2CAP_CONRES :
{
printf("\n \n*****Connection Response******* \n");
printf("El campo Code es de valor %X \n",L2CAPcon_res_RX.Code);
printf("El campo ID es de valor %X \n",L2CAPcon_res_RX.ID);
printf("El campo Length es de valor %X \n",L2CAPcon_res_RX.Length);
printf("El campo DCID es de valor %X \n",L2CAPcon_res_RX.DCID);
printf("El campo SCID es de valor %X \n",L2CAPcon_res_RX.SCID);
printf("El campo Result es de valor %X \n",L2CAPcon_res_RX.Result);
printf("El campo Status es de valor %X \n \n",L2CAPcon_res_RX.Status);
break;
}
}
}
int L2capChannel::entradaComandos (Tpdu_L2CAP pdu, unsigned int longitud)
{
int res;
unsigned int n, tipocomando;
// Comprobamos que realmente se ha recibido una trama de control
if (!(*(pdu+2)==0x01)&(*(pdu+3)==0x00))
{
cout<<"Esperado trama-C. Entrada no valida."<<endl;
return 1;
}
cout<<"Efectivamente era una trama de control. Ya estamos en el CANAL."<<endl;
n = 4;
_receivedIdentifier = *(pdu+5); // de momento, sin considerar varios comandos en 1 trama-C
tipocomando = *(pdu+n);
switch (tipocomando)
{
case L2CAP_CONREQ:
{
leerL2CAPcon_req(pdu,n);
break;
}
case L2CAP_CONRES:
{
res = leerL2CAPcon_res(pdu,n);
break;
}
default :
{
cout <<"Comando no valido."<<endl;
return 2;
break;
}
}
situacion ();
return 0;
}
void L2capChannel::situacion ()
// Saca por pantalla el estado en el que nos encontramos
{
switch (_estado)
{
case CLOSED :
{
printf("\t \t Estado = CLOSED \n \n");
break;
}
case WAIT_CONNECT :
{
printf("\t \t Estado = WAIT_CONNECT \n \n");
break;
}
case WAIT_CONNECT_RSP :
{
printf("\t \t Estado = WAIT_CONNECT_RSP \n \n");
break;
}
case OPEN :
{
printf("\t \t Estado = OPEN \n \n");
break;
}
case WAIT_DISCONNECT :
{
printf("\t \t Estado = WAIT_DISCONNECT \n \n");
break;
}
case WAIT_CONFIG :
{
printf("\t \t Estado = WAIT_CONFIG \n \n");
break;
}
case WAIT_SEND_CONFIG :
{
printf("\t \t Estado = WAIT_SEND_CONFIG \n \n");
break;
}
case WAIT_CONFIG_REQ_RSP :
{
printf("\t \t Estado = WAIT_CONFIG_REQ_RSP \n \n");
break;
}
case WAIT_CONFIG_RSP :
{
printf("\t \t Estado = WAIT_CONFIG_RSP \n \n");
break;
}
case WAIT_CONFIG_REQ :
{
printf("\t \t Estado = WAIT_CONFIG_REQ \n \n");
break;
}
default :
{
}
}
}
string L2capChannel::arrayToString(Tpdu_L2CAP a)
{
unsigned int longitud,num,cal;
longitud = *(a) + (*(a+1))*256;
string result = "";
for (int i=0; i<longitud; i++)
{
num = a[i];
if (Esnumero(char((num/16)+'0')))
{
result = result + char((num/16)+'0');
}
else
{
result = result + char((num/16)+'A'-10);
}
cal=(num-(num/16)*16);
if (Esnumero(char( cal+'0')))
{
result = result + char(cal+'0');
}
else
{
result = result + char(cal+'A'-10);
}
}
return result;
}
bool L2capChannel::Esnumero (char valor)
{
bool test;
switch (valor)
{
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '0':
{
test = true;
break;
}
default :
{
test = false;
break;
}
}
return test;
}
void L2capChannel::sendComando (unsigned int tipocomando)
{
string cad;
Tpdu_L2CAP dataout ={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
printf("\n Se va a enviar a continuacion una PDU de contenido: \n");
switch (tipocomando)
{
case L2CAP_CONREQ : //0x02
{
vuelcaL2CAPcon_req(dataout);
imprimeArray (dataout,L2CAPcon_req_TX.Length + 8);
break;
}
case L2CAP_CONRES : //0x03
{
vuelcaL2CAPcon_res(dataout);
imprimeArray (dataout,L2CAPcon_res_TX.Length + 8);
break;
}
default : {
printf("Error. Campo Codigo incorrecto en SendComando \n");
}
}
cad = arrayToString(dataout);
cout<<"Se va a enviar por el socket una PDU de contenido: "<<cad<<endl;
// sockCanal->SendBytes(cad); // Canal manda mensaje por socket, si pasasemos el puntero a socket en el constructor
// pt2Func (_ME,cad); // Llama al Wrapper y éste deberia escribir, pero no lo hace
} //SendComando
// ********FUNCIONES DE VOLCADO DE DATOS DESDE LAS VARIABLES REGISTRO********
// ******************** AL ARRAY DE SALIDA (PDU)****************************
void L2capChannel::vuelcaL2CAPcon_req(Tpdu_L2CAP &dataout)
{
unsigned int longitud,ind,res,coc;
longitud = L2CAPcon_req_TX.Length;
coc = longitud + 4;
for (ind=0;(ind<2);ind++)
{
res = coc % 256;
*(dataout+ind) = res;
coc = coc / 256;
}
*(dataout+ind) = 0x1; // trama de control
ind++;
*(dataout+ind) = 0x0;
ind++;;
*(dataout+ind) = L2CAPcon_req_TX.Code;
ind++;
*(dataout+ind)= L2CAPcon_req_TX.ID;
ind++;
coc = L2CAPcon_req_TX.Length;
for (ind=6;(ind<8);ind++)
{
res = coc % 256;
*(dataout+ind) = res;
coc = coc / 256;
}
coc = L2CAPcon_req_TX.PSM;
for (ind=8;(ind<10);ind++)
{
res = coc % 256;
*(dataout+ind) = res;
coc = coc / 256;
}
coc = L2CAPcon_req_TX.SCID;
for (ind=10;(ind<12);ind++)
{
res = coc % 256;
*(dataout+ind) = res;
coc = coc / 256;
}
}
void L2capChannel::vuelcaL2CAPcon_res(Tpdu_L2CAP &dataout)
{
unsigned int longitud,ind,res,coc;
longitud = L2CAPcon_res_TX.Length;
coc = longitud + 4;
for (ind=0;(ind<2);ind++)
{
res = coc % 256;
*(dataout+ind) = res;
coc = coc / 256;
}
*(dataout+ind) = 0x1; // trama de control
ind++;
*(dataout+ind) = 0x0;
ind++;;
*(dataout+ind) = L2CAPcon_res_TX.Code;
ind++;
*(dataout+ind)= L2CAPcon_res_TX.ID;
ind++;
coc = L2CAPcon_res_TX.Length;
for (ind=6;(ind<8);ind++)
{
res = coc % 256;
*(dataout+ind) = res;
coc = coc / 256;
}
coc = L2CAPcon_res_TX.DCID;
for (ind=8;(ind<10);ind++)
{
res = coc % 256;
*(dataout+ind) = res;
coc = coc / 256;
}
coc = L2CAPcon_res_TX.SCID;
for (ind=10;(ind<12);ind++)
{
res = coc % 256;
*(dataout+ind) = res;
coc = coc / 256;
}
coc = L2CAPcon_res_TX.Result;
for (ind=12;(ind<14);ind++)
{
res = coc % 256;
*(dataout+ind) = res;
coc = coc / 256;
}
coc = L2CAPcon_res_TX.Status;
for (ind=14;(ind<(longitud+8));ind++)
{
res = coc % 256;
*(dataout+ind) = res;
coc = coc / 256;
}
}
int L2capChannel::connectChannel()
{
cout<<endl<<endl<<"Creando CANAL"<<endl<<endl;
if (_estado == CLOSED)
{
srand(time(NULL));
_identifier=rand();
escribeL2CAPcon_req_TX ();
sendComando (L2CAP_CONREQ);
_estado = WAIT_CONNECT_RSP;
return 0;
}
else
{
cout<<"Apertura canal no valida. Estado no CLOSED."<<endl;
return 1;
}
}