////////////////////////////////////////////////// // Bakalarska praca // // Meno studenta: Tomas Lukac // // Veduci BP: prof. Ing. Milos Drutarovsky CSc. // // Skola: KEMT FEI TUKE // // Datum poslednej upravy: 6.5.2020 // ////////////////////////////////////////////////// #include "komunikacia.h" #include "kryptografia.h" int poslat_subor(WOLFSSL* ssl, WOLFSSL_CTX* ctx, const char* cesta, nastavenia_aplikacie *nastavenia, int velkost_bloku_dat) { int uspech; while(wolfSSL_write(ssl, cesta, SPRAVA_VELKOST_BUFFERA) != SPRAVA_VELKOST_BUFFERA) { if(wolfSSL_want_write(ssl)) continue; fprintf(stderr, "Nastala chyba pri posielani nazvu suboru\n"); return -1; } //otvorenie suboru na citanie FILE* subor = fopen(cesta, "rb"); if(subor == NULL) { fprintf(stderr, "Nebolo mozne najst pozadovany subor.\n"); ukoncit_spojenie(ssl, ctx); return -1; } else { printf("Posielam subor.\n"); //nastavi ukazovatel na koniec suboru //a zisti velkost suboru fseek(subor, 0, SEEK_END); int velkost_suboru = (int)ftell(subor); char velkost_suboru_retazec[SPRAVA_VELKOST_BUFFERA]; sprintf(velkost_suboru_retazec, "%d", velkost_suboru); printf("Velkost suboru: %s bajtov\n", velkost_suboru_retazec); while(wolfSSL_write(ssl, velkost_suboru_retazec, SPRAVA_VELKOST_BUFFERA) != SPRAVA_VELKOST_BUFFERA) { if(wolfSSL_want_write(ssl)) continue; fprintf(stderr, "Nastala chyba pri posielani velkosti suboru\n"); return -1; } //nastavi ukazovatel na zaciatok suboru //a nacita data zo suboru do pola unsigned char* data = calloc(velkost_suboru, sizeof(unsigned char)); if(data == NULL) { fprintf(stderr, "Nepodarilo sa dynamicky alokovat pamat pre pole data,\ndo ktoreho sa nacita obsah suboru\n"); return -1; } fseek(subor, 0, SEEK_SET); fread((unsigned char*)data, 1, velkost_suboru, subor); //posielanie jednotlivych bajtov unsigned char* data_ukazovatel = data; uspech = 0; int ostava_poslat = velkost_suboru; for(int i = 0; i < (velkost_suboru/velkost_bloku_dat) + 1; ++i) { if(ostava_poslat > velkost_bloku_dat) { while(wolfSSL_write(ssl, data_ukazovatel, velkost_bloku_dat) != velkost_bloku_dat) { if(wolfSSL_want_write(ssl)) continue; fprintf(stderr, "Nastala chyba pri posielani suboru\n"); return -1; } } else { uspech = 0; while(wolfSSL_write(ssl, data_ukazovatel, ostava_poslat) != ostava_poslat) { if(wolfSSL_want_write(ssl)) continue; fprintf(stderr, "Nastala chyba pri posielani suboru\n"); return -1; } } data_ukazovatel += velkost_bloku_dat; ostava_poslat -= velkost_bloku_dat; } printf("Subor bol uspesne odoslany.\n"); //generovanie a poslanie kontrolneho suctu serveru pre kontrolu unsigned char* kontrolny_sucet; int velkost_kontrolneho_suctu; kontrolny_sucet = generovat_kontrolny_sucet_suboru(nastavenia, cesta, velkost_suboru, &velkost_kontrolneho_suctu); while(wolfSSL_write(ssl, kontrolny_sucet, velkost_kontrolneho_suctu) != velkost_kontrolneho_suctu) { if(wolfSSL_want_write(ssl)) continue; fprintf(stderr, "Nastala chyba pri posielani kontrolneho suctu\n"); return -1; } free(kontrolny_sucet); fclose(subor); return 0; } } int prijat_subor(WOLFSSL* ssl, WOLFSSL_CTX* ctx, nastavenia_aplikacie* nastavenia, int velkost_bloku_dat) { int uspech; //prijem dat o subore char* cesta = calloc(SPRAVA_VELKOST_BUFFERA, sizeof(char)); char* velkost_suboru_retazec = calloc(SPRAVA_VELKOST_BUFFERA, sizeof(char)); while(wolfSSL_read(ssl, cesta, SPRAVA_VELKOST_BUFFERA) != SPRAVA_VELKOST_BUFFERA) { if(wolfSSL_want_read(ssl)) continue; fprintf(stderr, "Nastala chyba pri prijati nazvu suboru\n"); return -1; } printf("Prebieha prijimanie suboru %s\n", cesta); //ziskanie informacie od klienta o velkosti odoslaneho suboru while(wolfSSL_read(ssl, velkost_suboru_retazec, SPRAVA_VELKOST_BUFFERA) != SPRAVA_VELKOST_BUFFERA) { if(wolfSSL_want_read(ssl)) continue; fprintf(stderr, "Nastala chyba pri prijati velkosti suboru\n"); return -1; } int velkost_suboru = (int)atol(velkost_suboru_retazec); if(velkost_suboru <= 0) { printf("Bola prijata informacia o velkosti suboru s hodnotu mensou nez 0\nPravdepodobne nastala chyba pri prenose\n"); return -1; } else { printf("Velkost suboru: %s bajtov\n", velkost_suboru_retazec); } //prijem jednotlivych bajtov unsigned char* data = calloc(velkost_suboru, sizeof(unsigned char)); if(data == NULL) { fprintf(stderr, "Nepodarilo sa dynamicky alokovat pamat pre pole data\ndo ktoreho sa zapisu prijate data\n"); return -1; } unsigned char* data_ukazovatel = data; int ostava_prijat = velkost_suboru; for(int i = 0; i < (velkost_suboru/velkost_bloku_dat) + 1; ++i) { if(ostava_prijat > velkost_bloku_dat) { while(wolfSSL_read(ssl, data_ukazovatel, velkost_bloku_dat) != velkost_bloku_dat) { if(wolfSSL_want_read(ssl)) continue; fprintf(stderr, "Nastala chyba pri prijimani suboru\n"); return -1; } } else { while(wolfSSL_read(ssl, data_ukazovatel, ostava_prijat) != ostava_prijat) { if(wolfSSL_want_read(ssl)) continue; fprintf(stderr, "Nastala chyba pri prijimani suboru\n"); return -1; } } data_ukazovatel += velkost_bloku_dat; ostava_prijat -= velkost_bloku_dat; } printf("Subor bol uspesne prijaty.\n"); //vypocet vlastneho kontrolneho suctu unsigned char* kontrolny_sucet; int velkost_kontrolneho_suctu; FILE *subor = fopen(cesta, "wb+"); int pocet_zapisanych_bajtov = fwrite((unsigned char*)data, 1, velkost_suboru, subor); if(pocet_zapisanych_bajtov <= 0) { fprintf(stderr, "Nepodarilo sa zapisat do suboru obsah prijateho suboru\n"); return -1; } else if(pocet_zapisanych_bajtov < velkost_suboru) { fprintf(stderr, "Nepodarilo sa zapisat do suboru cely obsah prijateho suboru\n"); return -1; } else { printf("Do suboru %s bolo zapisanych %d bajtov\n", cesta, pocet_zapisanych_bajtov); } fclose(subor); kontrolny_sucet = generovat_kontrolny_sucet_suboru(nastavenia, cesta, velkost_suboru, &velkost_kontrolneho_suctu); //prijem kontrolneho suctu, ktory vypocital server char* prijaty_kontrolny_sucet = calloc(velkost_kontrolneho_suctu, sizeof(char)); while(wolfSSL_read(ssl, (char*)prijaty_kontrolny_sucet, velkost_kontrolneho_suctu) != velkost_kontrolneho_suctu) { if(wolfSSL_want_read(ssl)) continue; fprintf(stderr, "Nastala chyba pri prijati kontrolneho suctu\n"); return -1; } //kontrola ci sa prijaty a vypocitany kontrolny sucet suboru zhoduju if(!strcmp((char*)prijaty_kontrolny_sucet, (char*)kontrolny_sucet)) { printf("Subor prisiel v poriadku.\n"); } else { fprintf(stderr, "Kontrolne sucty sa nezhoduju.\n"); printf("Subor neprisiel v poriadku alebo neboli pouzite rovnake funkcie.\n"); return -1; } free(cesta); free(velkost_suboru_retazec); free(kontrolny_sucet); free(prijaty_kontrolny_sucet); return 0; } int pripojit_na_server(char *ip_adresa, int cislo_portu, int pocet_sekund) { struct timeval casovy_interval; int uspech; int cislo_soketu; struct hostent* hostitel; struct sockaddr_in adresa; fd_set sada_soketov; socklen_t velkost_soketu; int optval; if((hostitel = gethostbyname(ip_adresa)) == NULL) { printf("Nastala chyba pri spracovani nazvu hostitela.\n"); return 0; } printf("Vytvaranie soketu...\n"); cislo_soketu = socket(AF_INET, SOCK_STREAM, 0); memset(&adresa, 0, sizeof(adresa)); adresa.sin_family = AF_INET; //IPv4 adresa.sin_port = htons(cislo_portu); adresa.sin_addr.s_addr = *(long*)(hostitel->h_addr); //pokus o pripojenie s casovym intervalom uspech = connect(cislo_soketu, (struct sockaddr*)&adresa, sizeof(adresa)); if(uspech < 0) { #if defined(_WIN32) if(errno == WSAEINPROGRESS ) #else if(errno == EINPROGRESS ) #endif { fprintf(stderr, "Nebolo mozne okamzite vytvorit spojenie\n"); do { casovy_interval.tv_sec = pocet_sekund; casovy_interval.tv_usec = 0; FD_ZERO(&sada_soketov); FD_SET(cislo_soketu, &sada_soketov); uspech = select(cislo_soketu + 1, NULL, &sada_soketov, NULL, &casovy_interval); #if defined(_WIN32) if (uspech < 0 && errno != WSAEINTR) #else if (uspech < 0 && errno != EINTR) #endif { fprintf(stderr, "Nastala chyba pri pokuse o vytvorenie spojenia\nCislo chyby: %d\nPopis: %s\n", errno, strerror(errno)); ukoncit_soket(cislo_soketu); exit(0); } //bol zvoleny soket else if(uspech > 0) { velkost_soketu = sizeof(int); if (getsockopt(cislo_soketu, SOL_SOCKET, SO_ERROR, (void*)(&optval), &velkost_soketu) < 0) { fprintf(stderr, "Nastala chyba v nastaveni soketu\nCislo chyby: %d\nPopis: %s\n", errno, strerror(errno)); ukoncit_soket(cislo_soketu); exit(0); } if(optval) { fprintf(stderr, "Nastala chyba v spojeni\nCislo chyby: %d\nPopis: %s\n", optval, strerror(optval)); ukoncit_soket(cislo_soketu); exit(0); } break; } else { fprintf(stderr, "Casovy interval vyprsal\n"); ukoncit_soket(cislo_soketu); exit(0); } } while(1); } else { fprintf(stderr, "Spojenie zlyhalo.\nCislo chyby: %d\nPopis: %s\n", errno, strerror(errno)); ukoncit_soket(cislo_soketu); exit(0); } } return cislo_soketu; } int cakat_na_komunikaciu(int cislo_portu) { int cislo_soketu; struct sockaddr_in adresa; printf("Vytvaranie socketu...\n"); cislo_soketu = socket(PF_INET, SOCK_STREAM, 0); memset(&adresa, 0, sizeof(adresa)); adresa.sin_family = AF_INET; //IPv4 adresa.sin_port = htons(cislo_portu); adresa.sin_addr.s_addr = INADDR_ANY; if(bind(cislo_soketu, (struct sockaddr*)&adresa, sizeof(adresa)) != 0) { fprintf(stderr, "Nebolo mozne priradit soket ku danemu portu.\n"); return 0; } //maximalna velkost do ktorej rada cakajucich spojeni pre soket moze rast int velkost_radu = 10; if(listen(cislo_soketu, velkost_radu) != 0) { fprintf(stderr, "Na danom porte nie je mozne cakat na komunikaciu.\n"); return 0; } else { printf("Server caka na komunikaciu na porte %d.\n", cislo_portu); } return cislo_soketu; } int rs232_otvorit_rozhranie(int cislo_rozhrania, int rychlost, char* rezim, int kontrola_toku_dat) { int uspech = 0; uspech = RS232_OpenComport(cislo_rozhrania, rychlost, rezim, kontrola_toku_dat); if(uspech == 1) { fprintf(stderr, "Nebolo mozne otvorit seriove rozhranie\n"); return -1; } return 0; } int rs232_zatvorit_rozhranie(int cislo_rozhrania) { RS232_CloseComport(cislo_rozhrania); return 0; } int rs232_odoslat_spravu(int cislo_rozhrania, char* sprava, int velkost_spravy) { int uspech = 0; int odoslane_data = 0; //kontrolne vzory, ktore jednoznacne identifikuju zaciatok a koniec spravy unsigned char kontrolny_vzor[] = {0xAA, 0xAA, 0xAA, 0xAA}; //vytvorenie bajtov ktore budu niest informaciu o velkosti posielanej spravy unsigned char* velkost_spravy_hex = calloc(4, sizeof(unsigned char)); velkost_spravy_hex[0] = (velkost_spravy >> 24) & 0xFF; velkost_spravy_hex[1] = (velkost_spravy >> 16) & 0xFF; velkost_spravy_hex[2] = (velkost_spravy >> 8) & 0xFF; velkost_spravy_hex[3] = velkost_spravy & 0xFF; //vypocet kontrolneho suctu spravy unsigned int kontrolny_sucet = crc32(0L, Z_NULL, 0); if(velkost_spravy < 10) { kontrolny_sucet = crc32(kontrolny_sucet, (char*)sprava, velkost_spravy); } else { kontrolny_sucet = crc32(kontrolny_sucet, (char*)sprava, 10); } //vytvorenie bajtov ktore budu niest informaciu s kontrolnym suctom posielanej spravy unsigned char* kontrolny_sucet_hex = calloc(4, sizeof(unsigned char)); kontrolny_sucet_hex[0] = (kontrolny_sucet >> 24) & 0xFF; kontrolny_sucet_hex[1] = (kontrolny_sucet >> 16) & 0xFF; kontrolny_sucet_hex[2] = (kontrolny_sucet >> 8) & 0xFF; kontrolny_sucet_hex[3] = kontrolny_sucet & 0xFF; //odoslanie kontrolneho vzoru uspech = RS232_SendBuf(cislo_rozhrania, (unsigned char*)kontrolny_vzor, 4); if(uspech <= 0) { fprintf(stderr, "Nastala chyba pri odoslani kontrolneho vzoru\n"); return -1; } //odoslanie velkosti spravy uspech = RS232_SendBuf(cislo_rozhrania, (unsigned char*)velkost_spravy_hex, 4); if(uspech <= 0) { fprintf(stderr, "Nastala chyba pri odoslani velkosti spravy\n"); return -1; } //odoslanie kontrolneho suctu uspech = RS232_SendBuf(cislo_rozhrania, (unsigned char*)kontrolny_sucet_hex, 4); if(uspech <= 0) { fprintf(stderr, "Nastala chyba pri odoslani kontrolneho suctu\n"); return -1; } //odoslanie dat odoslane_data = RS232_SendBuf(cislo_rozhrania, (unsigned char*)sprava, velkost_spravy); if(odoslane_data <= 0 || odoslane_data != velkost_spravy) { fprintf(stderr, "Nastala chyba pri odoslani dat\n"); return -1; } free(velkost_spravy_hex); free(kontrolny_sucet_hex); return odoslane_data; } int rs232_prijat_spravu(int cislo_rozhrania, const char* komunikacny_subor) { //otvorenie suboru do ktoreho sa zapisuju prijate binarne data //ktore sa nasledne nacitaju do buffera (buf) pre desifrovanie FILE* subor = fopen(komunikacny_subor, "ab+"); int uspech = 0; stav_nacitania stav; stav = NEPREBIEHA_NACITANIE; unsigned char znak; //mnozstvo nacitanych dat int nacitane_data = 0; //kontrolny vzor ktory jednoznacne identifikuje zaciatok spravy unsigned char kontrolny_vzor[] = {0xAA, 0xAA, 0xAA, 0xAA}; //urcuje kolko bajtov z kontrolneho vzoru //uz bolo prijatych z celkoveho poctu (4) int kontrolny_vzor_pozicia = 0; //velkost spravy, ktora sa bude prijmat int velkost_spravy = 0; unsigned char velkost_spravy_hex[4]; //urcuje kolko bajtov z informacie o velkosti spravy //uz bolo prijatych z celkoveho poctu (4) int velkost_spravy_pozicia = 0; //kontrolny sucet, ktory sa bude prijimat int kontrolny_sucet = 0; unsigned char kontrolny_sucet_hex[4]; //urcuje kolko bajtov z kontrolneho suctu //uz bolo prijatych z celkoveho poctu (4) int kontrolny_sucet_pozicia = 0; unsigned char* prijate_data; while(stav != NACITANIE_UKONCENE) { uspech = RS232_PollComport(cislo_rozhrania, &znak, 1); if(uspech > 0) { switch(stav) { case NEPREBIEHA_NACITANIE: if(znak == kontrolny_vzor[kontrolny_vzor_pozicia]) { kontrolny_vzor_pozicia++; } if(kontrolny_vzor_pozicia == 4) { kontrolny_vzor_pozicia = 0; stav = PREBIEHA_NACITANIE_VELKOSTI_SPRAVY; } break; case PREBIEHA_NACITANIE_VELKOSTI_SPRAVY: velkost_spravy_hex[velkost_spravy_pozicia] = znak; velkost_spravy_pozicia++; if(velkost_spravy_pozicia == 4) { velkost_spravy = (uint32_t)velkost_spravy_hex[0] << 24 | (uint32_t)velkost_spravy_hex[1] << 16 | (uint32_t)velkost_spravy_hex[2] << 8 | (uint32_t)velkost_spravy_hex[3]; velkost_spravy_pozicia = 0; stav = PREBIEHA_NACITANIE_KONTROLNEHO_SUCTU; //dynamicka alokacia pola s velkostou, ktora bola prijata //do neho bude zapisana prijata sprava prijate_data = calloc(velkost_spravy, sizeof(unsigned char)); if(prijate_data == NULL) { fprintf(stderr, "Nepodarilo sa dynamicky alokovat pamat pre prijate_data\n"); return -1; } } break; case PREBIEHA_NACITANIE_KONTROLNEHO_SUCTU: kontrolny_sucet_hex[kontrolny_sucet_pozicia] = znak; kontrolny_sucet_pozicia++; if(kontrolny_sucet_pozicia == 4) { kontrolny_sucet = (uint32_t)kontrolny_sucet_hex[0] << 24 | (uint32_t)kontrolny_sucet_hex[1] << 16 | (uint32_t)kontrolny_sucet_hex[2] << 8 | (uint32_t)kontrolny_sucet_hex[3]; kontrolny_sucet_pozicia = 0; stav = PREBIEHA_NACITANIE_DAT; } break; case PREBIEHA_NACITANIE_DAT: prijate_data[nacitane_data] = znak; nacitane_data += uspech; if(nacitane_data == velkost_spravy) { stav = NACITANIE_UKONCENE; } break; default: //tento stav by nemal nikdy nastat fprintf(stderr, "Nepodarilo sa urcit stav nacitania spravy pomocou RS232\n"); return -1; } } } //kontrola integrity prijatej spravy //vypocet kontrolneho suctu prijatej spravy unsigned int kontrolny_sucet_ps = crc32(0L, Z_NULL, 0); if(velkost_spravy < 10) { kontrolny_sucet_ps = crc32(kontrolny_sucet_ps, (char*)prijate_data, velkost_spravy); } else { kontrolny_sucet_ps = crc32(kontrolny_sucet_ps, (char*)prijate_data, 10); } //porovnanie kontrolnych suctov if(kontrolny_sucet_ps == kontrolny_sucet) { //ak sprava prisla v poriadku zapis nacitane data do suboru fwrite((char*)prijate_data, 1, nacitane_data, subor); } else { fprintf(stderr, "Sprava neprisla v poriadku"); return -1; } free(prijate_data); fclose(subor); return nacitane_data; }