LINUX.ORG.RU

Сообщения stD

 

Размер выделенного массива (СИ)

Здравствуйте.

Выделяю память под массив:

char *tochdost = calloc(64+64+64+64, sizeof(char));

if(tochdost != NULL)  
 {
   char *encrypt = tochdost + 64;
   char *res_encrypt = encrypt + 64;
   char *pasword = res_encrypt + 64;
   ...

Смотрю размер выделенной области вот так:

printf("SIZE %zu\n", malloc_usable_size(tochdost));

В ответ получаю - SIZE 264.

Скажите, откуда берутся лишние 8 байт?

Язык СИ, Линукс.

 

stD
()

Как правильно закрывать popen?

Здравствуйте.

Помогите разобраться с закрытием потока, открытого popen: Язык СИ, линукс.

char curl_buff[64] = {0,};

FILE *curl_prog = popen("curl http://192.168.5.189 2> /dev/null", "r");

if(curl_prog != NULL)
 {
   fgets(curl_buff, 63, curl_prog);
 }

if(pclose(curl_prog) == -1) error_log("close curl_prog.");

Закрытие должно быть после фигурных скобок или внутри...?

char curl_buff[64] = {0,};

FILE *curl_prog = popen("curl http://192.168.5.189 2> /dev/null", "r");

if(curl_prog != NULL)
 {
   fgets(curl_buff, 63, curl_prog);
   if(pclose(curl_prog) == -1) error_log("close curl_prog.");
 }

То есть, мне не понятно, если curl_prog вернул NULL, то это значит что?

Поток открылся после этой строчки:

FILE *curl_prog = popen("curl http://192.168.5.189 2> /dev/null", "r");

Или ещё не ясно, открылся он или нет и это проверяется здесь:

if(curl_prog != NULL)
 {
   ...

 

stD
()

Проверка выделения памяти (си)

Здравствуйте.

Скажите, нужно ли проверять выделение памяти, если я запрашиваю всего один байт?

char *str = (char*)malloc(1 * sizeof(char));

Какие могут быть причины НЕ выделения?

Спасибо.

 

stD
()

Размер выделяемой памяти

Здравствуйте.

Скажите пожалуйста, как будет правильней выделять количество памяти. Кратно (8, 32, 64) или столько сколько нужно?

То есть, допустим мне нужно 10 байт, как будет лучше/правильней, выделить 11 байт или 16?

Извиняюсь за корявую постановку вопроса.))) Спасибо.

 

stD
()

Telegrambot на СИ - SSL_read

Здравствуйте.

Пишу сервер для бота работающий через Webhook. Вот код (только main):

int main() 
{  
    ////////////////////////////////////    ssl    //////////////////////////////////////////
    OpenSSL_add_all_algorithms();
    SSL_load_error_strings();
    SSL_library_init();
    SSL_CTX * sslctx = SSL_CTX_new(TLSv1_2_server_method());

    /////////////////////////////    read certificate    ////////////////////////////////////
    if(SSL_CTX_use_certificate_file(sslctx, "cert.pem", SSL_FILETYPE_PEM) <= 0) error_log("use_certificate_file!");
    if(SSL_CTX_use_PrivateKey_file(sslctx, "cert.pem", SSL_FILETYPE_PEM) <= 0) error_log("use_PrivateKey_file!");
    if(!SSL_CTX_check_private_key(sslctx)) error_log("check_private_key!");

    ///////////////////////////////////    server    ////////////////////////////////////////
    int sd = socket(AF_INET, SOCK_STREAM, 0); 
    if (sd < 0) error_log("descriptor socket!");
    int one = 1;
    setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int));
 
    struct sockaddr_in s_addr;
    s_addr.sin_family = AF_INET;
    s_addr.sin_addr.s_addr = INADDR_ANY;
    s_addr.sin_port = htons(port);

    if(bind(sd, (struct sockaddr *)&s_addr, sizeof(s_addr)) < 0) error_log("binding!");

    if(listen(sd, 5) == -1) 
     {
       close(sd);
       error_log("listen!");
     }


    char read_buffer[BREADSIZE] = {0,};

    while(1) 
     {  
        printf("ROUTER WAIT CONNECTION.\n");
        memset(read_buffer, 0, BREADSIZE);
        int client = accept(sd, NULL, NULL); 

        ///////////////////////////// ssl socket //////////////////////////////
        SSL *ssl = SSL_new(sslctx);
        if(SSL_set_fd(ssl, client) == 0) error_log("SSL_set_fd!");

        int acc = SSL_accept(ssl); 
        if(acc <= 0)
         { 
            SSL_free(ssl);
            if(close(client) == -1) error_log("close client_2!");
            error_log("Not SSL_accept.");
            continue;
         }
         
        /////////////////////////////// fork ///////////////////////////////////
        pid_t fpid;  
        signal(SIGCHLD, child_kill);  
        fpid = fork();

        /////////////////////////// start child ////////////////////////////////
        if(fpid != 0) 
         { 
            SSL_free(ssl);
            if(close(client) == -1) error_log("close client_pid!");
            continue;
         }
         
        ///////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////// read header from telegram //////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////////////////////
        int n = SSL_read(ssl, read_buffer, BREADSIZE - 2); // first SSL_read
        if(n <= 0)
         {
            SSL_free(ssl);
            if(close(client) == -1) error_log("close client_3!");
            printf("Disconnection:%d\n", n);
            exit(0);           
         } 

printf("READ_BUFER:%s_END\n\n", read_buffer);

        ////////////////////////////////////////////////////////////////////////
        /////////////////////////// read json data ///////////////////////////// 
        ////////////////////////////////////////////////////////////////////////
        memset(read_buffer, 0, BREADSIZE); 
        int m = SSL_read(ssl, read_buffer, BREADSIZE - 2);  // second SSL_read
        if(m <= 0)
         {
            SSL_free(ssl);
            if(close(client) == -1) error_log("close client_8!");
         }
         
printf("READ_JSON:%s_END\n\n", read_buffer);

        //////////////////////////// telegram reply  //////////////////////////////
        SSL_write(ssl, "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n", 38);
        SSL_free(ssl);
        if(close(client) == -1) error_log("close client_6!");
        exit(0); 
  
    } // END while(1) 
 
}

Код работает, но вот в чём вопрос: приходится делать SSL_read два раза. То есть, при первом чтении (first SSL_read) считывается заголовок:

READ_BUFER:POST /55454634:AAEJ2Z930r3oyno6kTA97gWGj2osSUXI HTTP/1.1
Host: 6.129.231.13
Content-Type: application/json
Content-Length: 308
Connection: keep-alive
Accept-Encoding: gzip, deflate

А во-втором (second SSL_read) читаются json-данные:

READ_JSON:{"update_id":33,"message":{"message_id":209,"from": бла-бла"}}_END

Если же делать такой же запрос к серверу с помощью curl'a, то всё читается в первом SSL_read.

Почему так происходит, может кто-нибудь объяснить? Может это особенность работы телеграмма? Или я всё неправильно делаю?

Спасибо.

 ,

stD
()

Как поменять пароль на линукс-машине POST или GET запросом

Предположим есть удалённая машина, на ней крутится самописный сервер (или какой-нибудь стандартный), как можно из браузера поменять пароль?

 ,

stD
()

HEX to char (в программе на СИ)

Здравствуйте.

Есть сервер на СИ, который должен принимать строку из браузера отправленную POST-запросом через Ajax. Строки (в браузере) вводятся через поля <input>. Так вот, некоторые символы приходят в виде HEX, например - dima:dimon приходит в таком виде - dima%3Adimon.

Как это переводить в читаемые символы?

 

stD
()

Помогите разобраться с malloc СИ

Здравствуйте.

Есть функция в которой есть две переменные для массивов - buff и trans_rate:

void rate_coin(char *coin)
 {
    FILE *rat_coi;
    char *buff = (char*) malloc(128 * sizeof(char));
    snprintf(buff, (int)strlen(coin) + 59, "%s%s%s", "curl https://api.coinmarketcap.com/v1/ticker/", coin, "/ 2>/dev/null"); 
    printf("Coinmarketcap: %s\n", buff);
    rat_coi = popen(buff, "r"); 
    if(rat_coi == NULL) error_log("rat_coi!");

    char trans_rate[128] = {0,};
    //char *trans_rate = (char*) malloc(128 * sizeof(char));
    int count = 0;
    strcat(trans_rate, "RATE COIN\n");
    memset(buff, 0, 128);
    while(fgets(buff, 126, rat_coi) != NULL)
     {
       count++;
       if(count > 8) break;
       if(count == 4 || count == 7 || count == 8)
        {
          char *pch = strtok(buff, " ,\"");
          while(pch != NULL)
           {
             char *ptr = strchr(pch, ':');
             if(ptr!=NULL) *ptr = ' ';
             strcat(trans_rate, pch);
             pch = strtok(NULL, " ,\"");
           }
        }
     }

    trans_rate[strlen(trans_rate) - 1] = 0;
    SendMessage(glob_chat_id, trans_rate);
    free(buff);
    printf("%s\n\n", trans_rate);
    //free(trans_rate);
 }

Для переменной buff делаю malloc, использую её в функции snprintf(buff, ...). После этого очищаю buff с помощью memset(buff,...), использую её же в функции while(fgets(buff,...) и в конце освобождаю память - free(buff);.

Для переменной trans_rate выделяю нужное кол-во байт и использую её.

Всё работает хорошо.

Если же для переменной trans_rate тоже делать malloc (строчка закомментирована) вместо char trans_rate[128] = {0,};, то прога начинает вести себя непредсказуемо, как будто перекрываются массивы (в printf попадают непонятные символы):

h�"�WRATE COIN

Объясните пожалуйста, почему в данном случае для buff malloc работает, а для trans_rate нет?

 ,

stD
()

Работа с массивом на СИ

Здравствуйте.

Суть вот в чём: мне нужно проверить наличие подстроки (она всегда в самом начале строки) в строке, и всё что идёт после этой подстроки записать в другой массив.

Допустим делаю так:

char *restr;
char str[32] = {0,};
char res_mas[16] = {0,};
...

if((restr = strstr(str, "xa-xa")) != NULL) 
 {
   strcpy(res_mas, restr + 5);
...

То есть я сдвигаю указатель на длину подстроки и оставшееся копирую в конечный массив.

Вопрос заключается в том, могу ли я сделать так?

char str[32] = {0,};
char res_mas[16] = {0,};
...

if(strstr(str, "xa-xa") != NULL) 
 {
   strcpy(res_mas, str + 5);
...

В обоих случаях всё работает, но правильно ли так делать?

(только не пишите пожалуйста, что лучше использовать strncpy или memcpy, речь не об этом, strcpy нарисована в качестве примера)

...

И ещё «подвопрос»: если я использую несколько конструкций «if()» подряд...

char *restr;
char str[32] = {0,};
char res_mas[16] = {0,};
char res_mas2[16] = {0,};
char res_mas3[16] = {0,};
...

if((restr = strstr(str, "xa-xa")) != NULL) 
 {
   strcpy(res_mas, restr + 5);
 }

if((restr = strstr(str, "xo-xo")) != NULL) 
 {
   strcpy(res_mas2, restr + 5);
 }

if((restr = strstr(str, "xy-xy")) != NULL) 
 {
   strcpy(res_mas3, restr + 5);
 }

...то нужно ли после каждого блока if() «обнулять» указатель *restr? И если да, то как это делать правильно?

Заранее спасибо.

 ,

stD
()

Приоритет операторов

Здравствуйте.

Совершенно дурацкий вопрос:

if(count == 10 && (strstr(buff, "бла-бла") != NULL || strstr(buff, "блу-блу"))

Если count НЕ равен 10, то будет ли дальше проверяться условия?

Или надо так?

if((count == 10) && (strstr(buff, "бла-бла") != NULL || strstr(buff, "блу-блу"))

 

stD
()

Создать ресурс для облачного майнинга

Здравствуйте.

Собственно вопрос вот в чём: мой товарищ предложил создать сервис для облачного майнинга. Сам я майню на «любительском» уровне (пара видеокарт) и конечно же не обладаю надлежащими знаниями.

Какие для этого понадобятся ресурсы, финансовые и главное человеческие. Ведь насколько я себе представляю, помимо кучи бабла нужна команда из программистов, экономистов и ещё разных людей. И сколько времени нужно потратить на реализацию подобного проекта?

Поделитесь своими мыслями и/или опытом в этом деле? Я бы потом дал это почитать своему товарищу, чтоб он успокоился )))

 

stD
()

Как убрать из строки символы цвета этой строки?

Здравствуйте.

Допустим имеется строка:

\x1b[31mЭта строка будет красного цвета\x1b[0m

Подскажите, есть ли в языки СИ какие-либо средства для удаления этих симолов (\x1b[31m, \x1b[0m)?

 

stD
()

Захват stdout'а какой-либо программы в своей программе (СИ)

Здравствуйте.

Я уже задавал подобный вопрос, ответ на него вроде бы прост:

#include <stdio.h>

int main() 
{
	FILE *in;
	char buff[512];

	if(!(in = popen("df -h", "r")))
         {
		printf("xana");
	 }

	while(fgets(buff, sizeof(buff), in)!=NULL)
         {
		printf("RECIV:%s", buff);
	 }

	pclose(in);
    return 0;
}

Получаю всё как положено.

RECIV:Файл.система   Размер Использовано  Дост Использовано% Cмонтировано в
RECIV:udev             3,9G         4,0K  3,9G            1% /dev
RECIV:tmpfs            799M         1,4M  798M            1% /run
RECIV:/dev/sdb1        143G         105G   31G           78% /
RECIV:none             4,0K            0  4,0K            0% /sys/fs/cgroup
RECIV:none             5,0M            0  5,0M            0% /run/lock
RECIV:none             3,9G          28M  3,9G            1% /run/shm
RECIV:none             100M          52K  100M            1% /run/user

Программа которую я планирую запускать (это майнер EWBF) подключается к пулу (передавая ему пароль) и начинает майнить.

Дык вот в чём дело: если запустить майнер с НЕ правильным паролем, то он выдаёт сообщение об ошибке, а моя программа ловит его и завершает работу.

RECIV:+-------------------------------------------------+
RECIV:|         EWBF's Zcash CUDA miner. 0.3.4b         |
RECIV:+-------------------------------------------------+
RECIV:INFO: Current pool: zec.suprnova.cc:2142
RECIV:INFO: Selected pools: 1
RECIV:INFO: Solver: Auto.
RECIV:INFO: Devices: All.
RECIV:INFO: Temperature limit: 90
RECIV:INFO: Api: Disabled
RECIV:---------------------------------------------------
RECIV:INFO: Target: 003c3c3c3c3c3c3c...
RECIV:INFO: Detected new work: 4902
RECIV:ERROR: Stratum authorization error

Если же запустить с правильными данными, то моя программа ничего не ловит, как будто майнер ничего не выдаёт (а он выдаёт).

То есть (как я думаю) когда майнер запускается с правильными данными, то внутри что-то форкается и инфа выдаётся неизвестно куда. (другого объяснения я не занаю)

Такое может быть? Или почему вобще так происходит?

П.С. Извиняюсь за формулировку вопроса и заранее спасибо.

 

stD
()

Захват stdout'а какой-либо программы в своей программе (СИ)

Здравствуйте.

Я хочу в своей программе запускать другую программу и ловить то, что она выдаёт в stdout.

Допустим делаю это так:

#include <stdio.h>

int main()
 {
   FILE * som_prog;
   char stroka[200];

   som_prog = popen("top", "r");

   while (!feof(som_prog))
    {
      fgets(stroka, 199, som_prog);
      printf("START: %s", stroka);
    }

   pclose(som_prog);
   printf("END\n");
   return 0;
 }

// gcc -Wall -Wextra as2.c -o as2

В данном случае запускаю «top» и получаю ожидаемое...

...
START:  9481 dima      20   0  617380  61688  49960 S   6,0  0,8  59:14.48 gnome-system-mo                                           
START:  2915 dima      20   0 1115668 196464  57604 S   2,3  2,4  73:16.01 plugin-containe                                           
START:  1417 root      20   0  358360 112796  88736 S   1,0  1,4  66:37.20 Xorg                                                      
START:  2501 dima      20   0 1514860 190560  71068 S   1,0  2,3  33:44.33 compiz                                                    
START:  5991 dima      20   0  656628  32728  23936 S   1,0  0,4   0:17.11 gnome-terminal 
...
...то есть всё хорошо.

Однако заковыка в другом. Мне нужно ловить данные от программы, которая сначала «плюёт» пару строк (и они успешно ловятся), а потом эта программа создаёт ещё один свой поток и «плюёт» строки уже из него. И вот эти строки уже не ловятся.

Что можно придумать?

 

stD
()

Как сделать так, чтоб самодельный сервер принимал только локальные соединения?

Здравствуйте.

Типа понадобился свой сервер, что-то вроде бекенда как в связке nginx + apache, где апач(мой сервер) принимает соединения только на - "... localhost:81>"

Я к тому, что, это как-то флагами какими-то устанавливается или нужно свою функцию писать?

Пишется на СИ.

Спасибо.

 

stD
()

Возьмите кто-нибудь меня на работу

Возьмите кто-нибудь меня на работу, пожалуйста.

Живу в Питере, возраст 40 лет.

Linux, программирование СИ, микроконтроллеры, Android.

Пишите на почту: pccar@mail.ru

 

stD
()

Про HTTPS

Здравствуйте.

Сегодня от гугла пришло письмо «счастья» с сообщением о понижении сайта ввиду отсутствия SSL-сертификата.

Естественно хочется бесплатно - кто-что посоветует и чем пользуется сам? Вроде как «Let's Encrypt» рекламируют.

И второй вопрос, который тяготит меня: если стоит связка nginx + apache, то настраивать нужно оба сервера или только nginx, который находится на «передовой»?

 

stD
()

Откуда в Search Console (google), в заблокированных ресурсах появился чужой сайт?

Зашёл сегодня в Search Console, посмотреть как там дела, и в разделе «Заблокированные ресурсы» обнаружил чужой сайт (подчеркнул красным). Объясните пожалуйста, откуда он там взялся?

https://hsto.org/files/ffd/4b5/3d1/ffd4b53d1bb941119e2b8434a1d42863.png

 

stD
()

WebSocket-сервер

Здравствуйте.

Пост пишется с целью послушать критику в адрес моего поделья, а так же в надежде на то, что это кому-то пригодится.

Суть в том, что захотелось мне написать на СИ лёгенький WebSocket-сервер для своих домашних целей. Найденные примеры оказались слишком избыточны и во многом меня не устраивали.

Сразу оговорюсь, сервер не умеет пересылать больше 125-ти байт, не умеет wss:// и не работает с фрагментированными фреймами.

В итоге вот что получилось:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <string.h>
#include <sys/stat.h> 
#include <fcntl.h>    
#include <time.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <sys/sendfile.h>

#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))

#if BYTE_ORDER == LITTLE_ENDIAN
#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
    |(rol(block->l[i],8)&0x00FF00FF))

#elif BYTE_ORDER == BIG_ENDIAN
#define blk0(i) block->l[i]

#else
#error "Endianness not defined!"
#endif

#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
    ^block->l[(i+2)&15]^block->l[i&15],1))

#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);

// opcode - тип фрейма
#define WS_TEXT_FRAME 0x01
#define WS_PING_FRAME 0x09
#define WS_PONG_FRAME 0x0A
#define WS_CLOSING_FRAME 0x08

#define BUFSIZE 1024
#define FILESTR 32
#define ALLARRAY 64
#define SHA_DIGEST_LENGTH 20

char response[] = "HTTP/1.1 200 OK\r\n"
"Content-Type: text/html; charset=UTF-8\r\n\r\n";

char response_404[] = "HTTP/1.1 404 Not Found\r\n"
"Content-Type: text/html; charset=UTF-8\r\n\r\n";

char response_img[] = "HTTP/1.1 200 OK\r\n"
"Content-Type: image/png; charset=UTF-8\r\n\r\n";  

char response_xicon[] = "HTTP/1.1 200 OK\r\n"
"Content-Type: image/x-icon; charset=UTF-8\r\n\r\n";

char response_css[] = "HTTP/1.1 200 OK\r\n"
"Content-Type: text/css; charset=UTF-8\r\n\r\n";

char response_js[] = "HTTP/1.1 200 OK\r\n"
"Content-Type: text/js; charset=UTF-8\r\n\r\n";

char response_ttf[] = "HTTP/1.1 200 OK\r\n"
"Content-Type: font/ttf ; charset=UTF-8\r\n\r\n";

char response_text[] = "HTTP/1.1 200 OK\r\n"
"Content-Type: text/text; charset=UTF-8\r\n\r\n";

char response_403[] = "HTTP/1.1 200 OK\r\n"
"Content-Type: text/html; charset=UTF-8\r\n\r\n"
"<!DOCTYPE html><html><head><title>403</title>"
"<style>body { background-color: #312f2f }"
"h1 { font-size:4cm; text-align: center; color: #666;}</style></head>"
"<body><h1>403</h1></body></html>\r\n";

char GUIDKey[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; //36

char response_ws[] = "HTTP/1.1 101 Switching Protocols\r\n"
"Upgrade: websocket\r\n"
"Connection: Upgrade\r\n"
"Sec-WebSocket-Accept: "; //97

unsigned char charset[]={"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"};

char patch_to_dir[ALLARRAY] = {0,};
char fpfile[ALLARRAY] = {0,};
char buffer[BUFSIZE] = {0,};
int client_fd, count_warning_log =0;
struct stat stat_buf;
sem_t sem;

typedef struct
 {
   uint32_t state[5];
   uint32_t count[2];
   unsigned char buffer[64];
 } SHA1_CTX;


/////////////////////////////////////////////// SHA1 /////////////////////////////////////////////////////////////
void SHA1Transform( uint32_t state[5], const unsigned char buffer[64])
 {
    uint32_t a, b, c, d, e;
    typedef union
     {
       unsigned char c[64];
       uint32_t l[16];
     } CHAR64LONG16;

    CHAR64LONG16 block[1];    
    memcpy(block, buffer, 64);

    a = state[0]; b = state[1]; c = state[2]; d = state[3]; e = state[4];

    R0(a, b, c, d, e, 0); R0(e, a, b, c, d, 1); R0(d, e, a, b, c, 2); R0(c, d, e, a, b, 3);
    R0(b, c, d, e, a, 4); R0(a, b, c, d, e, 5); R0(e, a, b, c, d, 6); R0(d, e, a, b, c, 7);
    R0(c, d, e, a, b, 8); R0(b, c, d, e, a, 9); R0(a, b, c, d, e, 10); R0(e, a, b, c, d, 11);
    R0(d, e, a, b, c, 12); R0(c, d, e, a, b, 13); R0(b, c, d, e, a, 14); R0(a, b, c, d, e, 15);
    R1(e, a, b, c, d, 16); R1(d, e, a, b, c, 17); R1(c, d, e, a, b, 18); R1(b, c, d, e, a, 19);
    R2(a, b, c, d, e, 20); R2(e, a, b, c, d, 21); R2(d, e, a, b, c, 22); R2(c, d, e, a, b, 23);
    R2(b, c, d, e, a, 24); R2(a, b, c, d, e, 25); R2(e, a, b, c, d, 26); R2(d, e, a, b, c, 27);
    R2(c, d, e, a, b, 28); R2(b, c, d, e, a, 29); R2(a, b, c, d, e, 30); R2(e, a, b, c, d, 31);
    R2(d, e, a, b, c, 32); R2(c, d, e, a, b, 33); R2(b, c, d, e, a, 34); R2(a, b, c, d, e, 35);
    R2(e, a, b, c, d, 36); R2(d, e, a, b, c, 37); R2(c, d, e, a, b, 38); R2(b, c, d, e, a, 39);
    R3(a, b, c, d, e, 40); R3(e, a, b, c, d, 41); R3(d, e, a, b, c, 42); R3(c, d, e, a, b, 43);
    R3(b, c, d, e, a, 44); R3(a, b, c, d, e, 45); R3(e, a, b, c, d, 46); R3(d, e, a, b, c, 47);
    R3(c, d, e, a, b, 48); R3(b, c, d, e, a, 49); R3(a, b, c, d, e, 50); R3(e, a, b, c, d, 51);
    R3(d, e, a, b, c, 52); R3(c, d, e, a, b, 53); R3(b, c, d, e, a, 54); R3(a, b, c, d, e, 55);
    R3(e, a, b, c, d, 56); R3(d, e, a, b, c, 57); R3(c, d, e, a, b, 58); R3(b, c, d, e, a, 59);
    R4(a, b, c, d, e, 60); R4(e, a, b, c, d, 61); R4(d, e, a, b, c, 62); R4(c, d, e, a, b, 63);
    R4(b, c, d, e, a, 64); R4(a, b, c, d, e, 65); R4(e, a, b, c, d, 66); R4(d, e, a, b, c, 67);
    R4(c, d, e, a, b, 68); R4(b, c, d, e, a, 69); R4(a, b, c, d, e, 70); R4(e, a, b, c, d, 71);
    R4(d, e, a, b, c, 72); R4(c, d, e, a, b, 73); R4(b, c, d, e, a, 74); R4(a, b, c, d, e, 75);
    R4(e, a, b, c, d, 76); R4(d, e, a, b, c, 77); R4(c, d, e, a, b, 78); R4(b, c, d, e, a, 79);

    state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e;
    a = b = c = d = e = 0;
    memset(block, 0, sizeof(block));
 }


void SHA1Init( SHA1_CTX * context)
 {
    context->state[0] = 0x67452301;
    context->state[1] = 0xEFCDAB89;
    context->state[2] = 0x98BADCFE;
    context->state[3] = 0x10325476;
    context->state[4] = 0xC3D2E1F0;
    context->count[0] = context->count[1] = 0;
 }


void SHA1Update( SHA1_CTX * context, const unsigned char *data, uint32_t len)
 {
    uint32_t i;
    uint32_t j;

    j = context->count[0];
    if ((context->count[0] += len << 3) < j) context->count[1]++;

    context->count[1] += (len >> 29);
    j = (j >> 3) & 63;
    if((j + len) > 63)
     {
       memcpy(&context->buffer[j], data, (i = 64 - j));

       SHA1Transform(context->state, context->buffer);
       for(; i + 63 < len; i += 64)
        {
          SHA1Transform(context->state, &data[i]);
        }

       j = 0;
     }

    else i = 0;

    memcpy(&context->buffer[j], &data[i], len - i);
 }


void SHA1Final( unsigned char digest[20], SHA1_CTX * context)
 {
    unsigned i;
    unsigned char c, finalcount[8];

    for(i = 0; i < 8; i++)
     {
       finalcount[i] = (unsigned char) ((context->count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8)) & 255);     
     }

    c = 0200;
    SHA1Update(context, &c, 1);

    while((context->count[0] & 504) != 448)
     {
       c = 0000;
       SHA1Update(context, &c, 1);
     }

    SHA1Update(context, finalcount, 8); 

    for(i = 0; i < 20; i++)
     {
       digest[i] = (unsigned char) ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255);
     }

    memset(context, 0, sizeof(*context));
    memset(&finalcount, 0, sizeof(finalcount));
 }


void SHA1(unsigned char *hash_out, const char *str, unsigned int len)
 {
    SHA1_CTX ctx;
    unsigned int ii;
    SHA1Init(&ctx);
    for (ii=0; ii<len; ii+=1) SHA1Update(&ctx, (const unsigned char*)str + ii, 1);
    SHA1Final((unsigned char *)hash_out, &ctx);
    hash_out[20] = 0;
 }


////////////////////////////////////// base64_encode ////////////////////////////////////////////
int base64_encode(unsigned char sha_key_in[], unsigned char base64_key_out[], int len)
 {
   int idx, idx2, blks, left_over;

   blks = (len / 3) * 3;
   for(idx=0, idx2=0; idx < blks; idx += 3, idx2 += 4) 
    {
      base64_key_out[idx2] = charset[sha_key_in[idx] >> 2];
      base64_key_out[idx2+1] = charset[((sha_key_in[idx] & 0x03) << 4) + (sha_key_in[idx+1] >> 4)];
      base64_key_out[idx2+2] = charset[((sha_key_in[idx+1] & 0x0f) << 2) + (sha_key_in[idx+2] >> 6)];
      base64_key_out[idx2+3] = charset[sha_key_in[idx+2] & 0x3F];
    }

   left_over = len % 3;

   if(left_over == 1) 
    {
      base64_key_out[idx2] = charset[sha_key_in[idx] >> 2];
      base64_key_out[idx2+1] = charset[(sha_key_in[idx] & 0x03) << 4];
      base64_key_out[idx2+2] = '=';
      base64_key_out[idx2+3] = '=';
      idx2 += 4;
    }

   else if(left_over == 2) 
    {
      base64_key_out[idx2] = charset[sha_key_in[idx] >> 2];
      base64_key_out[idx2+1] = charset[((sha_key_in[idx] & 0x03) << 4) + (sha_key_in[idx+1] >> 4)];
      base64_key_out[idx2+2] = charset[(sha_key_in[idx+1] & 0x0F) << 2];
      base64_key_out[idx2+3] = '=';
      idx2 += 4;
    }

   base64_key_out[idx2] = 0;
   return(idx2);
 }


////////////////////////////////////// error_log ////////////////////////////////////////////
void error_log(char *my_error) 
 { 
   time_t t;
   time(&t);
   FILE *f;
   f = fopen("/var/log/ErrorWsstd.log", "a"); 
   if(f == NULL) printf("Error open /var/log/ErrorWsstd.log.\n");
   fprintf(f, "%s", ctime( &t));
   fprintf(f, "Error %s\n\n", my_error);
   printf("Error %s Write to /var/log/ErrorWsstd.log.\n", my_error);
   fclose(f);
   exit(0);
 }


//////////////////////////////// warning_access_log ////////////////////////////////////////
void warning_access_log(char *war_ac) 
 {  
   count_warning_log++;
   if(count_warning_log > 100)
     {
       system("gzip -f /var/log/Access_warning.log");
       count_warning_log = 0;
       time_t t;
       time(&t);
       FILE *f;
       f = fopen("/var/log/Access_warning.log", "w"); 
       fprintf(f, "%s", ctime( &t));
       fprintf(f, "%s\n\n", war_ac);
       printf("_______________________________________\nWrite to /var/log/Access_warning.log...\n%s\n", war_ac);
       fclose(f);
     }

    else
     {
       time_t t;
       time(&t);
       FILE *f;
       f = fopen("/var/log/Access_warning.log", "a"); 
       fprintf(f, "%s", ctime( &t));
       fprintf(f, "%s\n\n", war_ac);
       printf("_______________________________________\nWrite to /var/log/Access_warning.log...\n%s\n", war_ac);
       fclose(f);
     }
 }


//////////////////////////////// read_in_file ////////////////////////////////////////
void read_in_file(char *name_file) 
 { 
   off_t offset = 0;
   memset(&stat_buf, 0, sizeof(stat_buf));    
   memset(fpfile, 0, ALLARRAY);
   snprintf(fpfile, (int)strlen(patch_to_dir) + (int)strlen(name_file) + 1, "%s%s", patch_to_dir, name_file);
   int file = open(fpfile, O_RDONLY);

   if(file < 0) 
    {
      if(close(client_fd) == -1) warning_access_log("open file close client_fd.");
      warning_access_log("Not File."); 
    }
 
   else
    {
      if(fstat(file, &stat_buf) != 0) error_log("fstat.");
      if(sendfile(client_fd, file, &offset, stat_buf.st_size) == -1) warning_access_log("sendfile."); 
      if(close(file) == -1) error_log("close file.");
      if(close(client_fd) == -1) warning_access_log("in function read_in_file() - close client_fd.");
      warning_access_log(buffer);
      printf("Trans %s\n\n", name_file);
    }
 }


///////////////////////////////////////// ws_func ///////////////////////////////////////////////////
void * ws_func(void *client_arg) 
 { 
   int client_fd = * (int *) client_arg;
   sem_post(&sem);
   warning_access_log("START_WS");
   printf("\nClient ID - %d\n", client_fd);
   char inbuf[132] = {0,};
   char reciv_r[48] = {0,};

   while(1)
    {
      memset(inbuf, 0, 132); 
      int rec_b = read(client_fd, inbuf, 131); // ожидаем данные от клиента и читаем их по приходу
      memset(reciv_r, 0, 48);
      snprintf(reciv_r, 39, "%s%d%s%d\n", "Ws_func recive ", rec_b, " bytes from clien ",  client_fd);
      warning_access_log(reciv_r); // пишем ссобытие в лог

      if(rec_b == 0 || rec_b == -1) // если клиент отвалился или что-то нехорошо, тогда...
       {
         memset(reciv_r, 0, 48);
         snprintf(reciv_r, 47, "%s%d%s%d\n", "Ws_func read return - ", rec_b, ", DIE clien - ",  client_fd);
         warning_access_log(reciv_r); // пишем ссобытие в лог
         if(close(client_fd) == -1) warning_access_log("Error close client in WS_1."); // закрываем соединение с клиентом
         pthread_exit(NULL);
       } 

      if(rec_b > 0)  // если чё то получили, то ...                    
       { 
         char masking_key[4] = {0,}; // сюда положим маску
         char opcode; // сюда тип фрейма
         int payload_len; // сюда длину сообщения (тела), то есть без служебных байтов 

         opcode = inbuf[0] & 0x0F;  
            printf("FIN: 0x%02x\n", inbuf[0] & 0x01);
            printf("RSV1: 0x%02x\n", inbuf[0] & 0x02);
            printf("RSV2: 0x%02x\n", inbuf[0] & 0x03);
            printf("RSV3: 0x%02x\n", inbuf[0] & 0x04);
            printf("Opcode: 0x%02x\n", inbuf[0] & 0x0F);
                      
         payload_len = inbuf[1] & 0x7F; 
            printf("Maska: 0x%02x\n", inbuf[1] & 0x80 ? 1:0);
            printf("Payload_len: %d\n", inbuf[1] & 0x7F);

         masking_key[0] = inbuf[2];
         masking_key[1] = inbuf[3];
         masking_key[2] = inbuf[4];
         masking_key[3] = inbuf[5];

              
         char payload[128] = {0,};

         if(opcode == WS_CLOSING_FRAME) // от клиента получен код закрытия соединения
          {
            memset(reciv_r, 0, 48);
            snprintf(reciv_r, 47, "%s%d\n", "Ws_func recive opcod - 0x08, DIE clien - ",  client_fd);
            warning_access_log(reciv_r); // пишем ссобытие в лог
            if(close(client_fd) == -1) warning_access_log("Error close client in WS_2."); // закрываем соединение с клиентом
            pthread_exit(NULL); // убиваем поtok
          }


         if(opcode == WS_PONG_FRAME) // от клиента получен PONG (маскированный)
          {
            int i = 6, pl = 0;
            for(; pl < payload_len; i++, pl++)
             {
               payload[pl] = inbuf[i]^masking_key[pl % 4]; 
             }
                     
            printf("\nRecive PONG and text \"%s\"\n", payload);
          }


         if(opcode == WS_TEXT_FRAME) // от клиента получен текст
          {
            int i = 6, pl = 0;
            for(; pl < payload_len; i++, pl++)
             {
               payload[pl] = inbuf[i]^masking_key[pl % 4]; 
             }
                     
            printf("\nReciv TEXT_FRAME from %d client, payload: %s\n", client_fd, payload);


            if(payload[0] == 'p' && payload[1] == 'i' && payload[2] == 'n' && payload[3] == 'g') // от клиента получен текст "ping"  
             {
               printf("\nPING client - %d\n", client_fd); 

               char ping[] = {0x89, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f}; // Ping - не маскированный, тело содержит слово Hello, эта же слово вернётся с Понгом
               
               if(send(client_fd, ping, 7, 0) == -1)
                {
                  warning_access_log("Error PING."); 
                  if(close(client_fd) == -1) warning_access_log("Error close client in WS_3."); // закрываем соединение с клиентом
                  pthread_exit(NULL); 
                }

             }

            if(payload[0] == 'c' && payload[1] == 'l' && payload[2] == 'o' && payload[3] == 's' && payload[4] == 'e') // от клиента получен текст "close"
             {
               printf("\nClose client - %d\n", client_fd); 

               char close_client[] = {0x88, 0};
               
               if(send(client_fd, close_client, 2, 0) == -1)
                {
                  warning_access_log("Error CLOSE."); 
                  if(close(client_fd) == -1) warning_access_log("Error close client in WS_4."); // закрываем соединение с клиентом
                  pthread_exit(NULL); 
                }

             }

            if(payload[0] == 'h' && payload[1] == 'i') // от клиента получен текст "hi"
             {
               char messag[] = "Hi client - ";
               int message_size = (int) strlen(messag);
               char out_data[128] = {0,};
               memcpy(out_data + 2, messag, message_size); // копируем сообщение в массив "out_data" начиная со второго байта (первые два байта для опкода и длины тела)
               char nom_client[5] = {0,};
               sprintf(nom_client, "%d", client_fd); // номер клиента
               int nom_client_size = (int) strlen(nom_client);
               memcpy(out_data + 2 + message_size, nom_client, nom_client_size); // копируем номер клиента в массив "out_data" следом за сообщением

               message_size += nom_client_size; // получаем общую длину тела сообщения

               out_data[0] = 0x81;
               out_data[1] = (char)message_size;

               printf("\nSize out Msg: %d\n", message_size);
               
               if(send(client_fd, out_data, message_size + 2, 0) == -1) 
                {
                  warning_access_log("Error Hi."); 
                  if(close(client_fd) == -1) warning_access_log("Error close client in WS_5."); // закрываем соединение с клиентом
                  pthread_exit(NULL); 
                }
              }

          }
   
       } // END if(n > 0)  
   
    } // END while(1)

 } // END ws_func



int main(int argc, char *argv[])  
{  
  if(argc != 3) error_log("not argumets.");
     
  unsigned int PORTW = strtoul(argv[1], NULL, 0); // порт для web-сервера 80
  strncpy(patch_to_dir, argv[2], 63); // путь к файлу index.html
  warning_access_log("START");
  pthread_t ws_thread;
  

  /////////////////////////////////////////////////////////    WEB    ///////////////////////////////////////////////////////////////
  int one = 1;
  struct sockaddr_in svr_addr, cli_addr;
  socklen_t sin_len = sizeof(cli_addr);
 
  int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (sock < 0) error_log("not socket.");
 
  setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int));
 
  svr_addr.sin_family = AF_INET;
  svr_addr.sin_addr.s_addr = INADDR_ANY;
  svr_addr.sin_port = htons(PORTW);

  if(bind(sock, (struct sockaddr *) &svr_addr, sizeof(svr_addr)) == -1) 
   {
     close(sock);
     error_log("bind.");
   }
 
  if(listen(sock, 5) == -1) 
   {
     close(sock);
     error_log("listen.");
   }


  signal(SIGPIPE, SIG_IGN);

  char str_from_buf[FILESTR] = {0,};
  char result_file[FILESTR] = {0,};

      
  for(;;) 
   {
    client_fd = accept(sock, (struct sockaddr *) &cli_addr, &sin_len);
 
    if(client_fd == -1) continue;

    printf("Сonnected %s:%d client - %d\n", inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port), client_fd);

    memset(buffer, 0, BUFSIZE);
    memset(str_from_buf, 0, FILESTR);
    memset(result_file, 0, FILESTR);
    char *p = NULL;

    if(read(client_fd, buffer, BUFSIZE - 1) == -1) warning_access_log("Error in main - read_client_fd.");

    int i = 0;
    for(; i < FILESTR; i++)
     {
       str_from_buf[i] = buffer[i];
       if(str_from_buf[i] == '\n') break;
       if(i > 31)
        {
          str_from_buf[i] = '\0';
          break;  
        }
     }


    if((strstr(str_from_buf, "GET / ")) != NULL) 
     {
       if(send(client_fd, response, (int)strlen(response), MSG_NOSIGNAL) == -1) warning_access_log("send response.");
       read_in_file("index.html");
     }


    /////////////////////////////////// WS /////////////////////////////////////////////////
    else if((strstr(str_from_buf, "GET /ws ")) != NULL) 
     {
       warning_access_log(buffer);
       if((p = strstr(buffer, "Sec-WebSocket-Key:")) != NULL)
        {                                                  
          char resultstr[64] = {0,};
          int i = 0, it = 0;
          for(i = 19; it < 24; i++, it++)
           {
             resultstr[it] = p[i];
           }

          strcat(resultstr, GUIDKey);

          printf("\n_____________|Key ot clienta__________|GUIDKey____________________________\n");
          printf("Result_stroka:%s\n", resultstr);


          ////////////////////////////sha1///////////////////////////////////////
          unsigned char temp[SHA_DIGEST_LENGTH] = {0,};
          SHA1(temp, resultstr, strlen(resultstr));


        ///////////////////// нужна только для того чтоб увидеть SHA1-хеш //////////////////////
          char buf[SHA_DIGEST_LENGTH*2] = {0,};                                               //
          for(i=0; i < SHA_DIGEST_LENGTH; i++)                                                // 
           {                                                                                  //
             sprintf((char*)&(buf[i*2]), "%02x", temp[i]);                                    //  
           }                                                                                  //
          printf("\nSHA1_hash:%s\n", buf);                                                    // 
        ////////////////////////////////////////////////////////////////////////////////////////


          ////////////////////////////Base64//////////////////////////////////// 
          unsigned char key_out[64] = {0,};
          base64_encode(temp, key_out, sizeof(temp));

          printf("\nKey_for_client:%s\n", key_out);

          sem_init(&sem, 0, 0);
          char resp[131] = {0,};
          snprintf(resp, 130, "%s%s%s", response_ws, key_out, "\r\n\r\n");
          if(send(client_fd, resp, sizeof(char) * strlen(resp), MSG_NOSIGNAL) == -1) warning_access_log("send response_ws.");
    

          //////////////////////////// START WS /////////////////////////////////
          if(pthread_create(&ws_thread, NULL, &ws_func, &client_fd) != 0) error_log("creating WS.");
          pthread_detach(ws_thread);
          sem_wait(&sem);
        }
     }

    else if((p = strstr(str_from_buf, ".png")) != NULL) 
     {
       int index = p - str_from_buf;
       int i = 0;
       int otbor = 0;
       for(; i < index + 3; i++)
        {
          result_file[i] = str_from_buf[i];
    
          if(result_file[i] == '/') 
           {
             otbor = i;
           }
        }

       memset(result_file, 0, FILESTR);
       strncpy(result_file, str_from_buf + otbor - 3, index -1); //  otbor + 1
       if(send(client_fd, response_img, (int)strlen(response_img), MSG_NOSIGNAL) == -1) warning_access_log("Error send response_img.");
       read_in_file(result_file);
     }

    else if((p = strstr(str_from_buf, ".css")) != NULL) 
     {
       int index = p - str_from_buf;
       int i = 0;
       int otbor = 0;
       for(; i < index + 3; i++)
        {
          result_file[i] = str_from_buf[i];
    
          if(result_file[i] == '/') 
           {
             otbor = i;
           }
        }

       memset(result_file, 0, FILESTR);
       strncpy(result_file, str_from_buf + otbor + 1, index -1);
       if(send(client_fd, response_css, (int)strlen(response_css), MSG_NOSIGNAL) == -1) warning_access_log("Error send response_css.");
       read_in_file(result_file);
     }


    else if((strstr(str_from_buf, "jquery.js")) != NULL) 
     {
       if(send(client_fd, response_js, (int)strlen(response_js), MSG_NOSIGNAL) == -1) warning_access_log("Error send response_js.");
       read_in_file("jquery.js");
     }

    else if((strstr(str_from_buf, "favicon.ico")) != NULL) 
     {
       if(send(client_fd, response_xicon, (int)strlen(response_xicon), MSG_NOSIGNAL) == -1) warning_access_log("Error send favicon.ico.");
       read_in_file("favicon.ico");
     }

    else 
     {
       if(send(client_fd, response_403, sizeof(response_403), MSG_NOSIGNAL) == -1) warning_access_log("Error send response_403.");
       if(close(client_fd) == -1) warning_access_log("Error close client_fd 403.");
       warning_access_log(buffer);
     }

   }// end for(;;)

} //END main



// gcc -Wall -Wextra -Werror websocket.c -o websocket -pthread 
// sudo ./websocket 85 /home/dima/Dropbox/ci/c-websocket/

#######################################################

Makefile для Openwrt

( Makefile для Openwrt )

index.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <!--<link rel="stylesheet" href="style.css" type="text/css" />-->

        <link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
        <!--<script src="jquery.js"></script>-->
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
  
        <style type="text/css">
           .knopka {
           height: 40px;
           width: 120px;
           text-align: center;
           line-height: 2.1;
           cursor: pointer;
           border: 1px solid #999;
           border-radius: 10px;
           }
           v{}
        </style>

        <script type="text/javascript">
            $(function() {
                window.WebSocket = window.WebSocket || window.MozWebSocket;
                var websocket = new WebSocket('ws://192.168.5.196:86/ws');


                websocket.onopen = function () {
                    $('h1').css('color', '#65c178'); /* green */
                };

                websocket.onclose = function (e) {
                    console.log("WebSocket: ", e)
                    $('h1').css('color', '#fe457e'); /* red */
                };


                websocket.onerror = function () {
                    $('h1').css('color', '#fe457e'); /* red */
     
                };

                websocket.onmessage = function (message) {
                    console.log(message.data);
                    $('v').append($('<p>', { text: message.data }));
                };
                
                $('.knp0').click(function(e) {
                    e.preventDefault();
                    websocket.send($('input').val());
                    $('input').val('');
                });

                $('.knp1').click(function(e) {
                    e.preventDefault();
                    websocket.send("hi");
                });

                $('.knp2').click(function(e) {
                    e.preventDefault();
                    websocket.send("ping");
                });



            });
        </script>
        </head>
    <body>
        <h1>WebSocket</h1>
     
          <div class='knopka knp1'>Hi...</div><br>
          <div class='knopka knp2'>Call PING</div><br>
          <div class='knopka knp0'>Send</div> <input type="text" />
          <v></v>
    </body>
</html>

Бинарник запускается с двумя параметрами — порт (80) и путь к папке с программой и файлом index.html.

Код содержит много ненужной отладочной информации и всяких логов. Так же есть некоторые неправильности (например потоки обращаются к одной и той же функции).

Заранее спасибо за все ваши высказывания.

П.С. То же самое я написал на geektimes, но там это не вызвало интереса.

 

stD
()

Вопрос про потоки и мьютексы (си)

Здравствуйте. Скажите пожалуйста...

Есть приложение, в нём несколько потоков (выполняют одну и ту же функцию со своими локальными переменными), эти потоки обращаются к глобальной переменной, но не изменяют её, а только читают. Нужно ли в этом случае ставить pthread_mutex_lock() ?

 

stD
()

RSS подписка на новые темы