Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/ioctl.h>
- #include <sys/poll.h>
- #include <sys/socket.h>
- #include <sys/time.h>
- #include <netinet/in.h>
- #include <errno.h>
- #include <map>
- #include <string.h>
- #include <errno.h>
- #include <unistd.h>
- #define SERVER_PORT 12345
- #define TRUE 1
- #define FALSE 0
- #define CONST 128
- #define BUF_LEN 1 << 20
- #define PORT 5001
- #define SSYMBOL(x) #x
- #define SYMBOL(X) SSYMBOL(X)
- #define F_NAME "log.txt"
- #include <iostream>
- #include <cstdio>
- #include <cstring>
- #include <cstdlib>
- #include <map>
- #include <fstream>
- #include <iomanip>
- #include <chrono>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <errno.h>
- #include <netinet/in.h>
- #include <sys/epoll.h>
- #include <arpa/inet.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <asn1/Request.h>
- #include <asn1/Response.h>
- int recvn(int sock, void *buf, int buflen) {
- int n, total = 0;
- while (total != buflen) {
- n = recv(sock, (char*) buf + total, buflen - total, 0);
- if (n <= 0)
- return n;
- total += n;
- }
- return total;
- }
- //проверка записи на соответсвие условиям из get запроса
- int check_record_get(LogRecord_t *rec, GetRequest_t &req) {
- return (((req.level && *req.level != rec->level)) ||
- ((req.begin && asn_GT2time(req.begin, nullptr, 0)
- > asn_GT2time(&rec->timestamp, nullptr, 0))) ||
- ((req.end && asn_GT2time(req.end, nullptr, 0)
- < asn_GT2time(&rec->timestamp, nullptr, 0)))) ? 0 : 1;
- }
- //проверка записи на соответсвие условия из clear запроса
- int check_record_clear(LogRecord_t *rec, ClearRequest_t &req) {
- return (asn_GT2time(&rec->timestamp, nullptr, 0)
- >= asn_GT2time(&req.choice.olderThan, nullptr, 0)) ? 0 : 1;
- }
- void process_request(Request_t *req, Response_t *&resp, FILE *&log,
- sockaddr_in &client) {
- if (req->present == Request_PR_add) {
- //заполняем поля
- AddRequest_t &areq = req->choice.add;
- LogRecord_t rec;
- memset(&rec, 0, sizeof(rec));
- rec.level = areq.level;
- rec.msg = areq.msg;
- {
- uint8_t *tmp = (uint8_t*)malloc(rec.msg.size);
- memcpy(tmp, rec.msg.buf, rec.msg.size);
- rec.msg.buf = tmp;
- }
- time_t tt = std::chrono::system_clock::to_time_t(
- std::chrono::system_clock::now());
- tm *pt = localtime(&tt);
- asn_time2GT(&rec.timestamp, pt, 0);
- rec.ip.present = IPAddress_PR_iPBinaryAddress;
- rec.ip.choice.iPBinaryAddress.present =
- IPBinaryAddress_PR_iPBinV4Address;
- //зрабиваем ip на байты и записываем
- char ip[4];
- ip[0] = client.sin_addr.s_addr & 0xFF;
- ip[1] = (client.sin_addr.s_addr >> 8) & 0xFF;
- ip[2] = (client.sin_addr.s_addr >> 16) & 0xFF;
- ip[3] = (client.sin_addr.s_addr >> 24) & 0xFF;
- OCTET_STRING_fromBuf(
- &rec.ip.choice.iPBinaryAddress.choice.iPBinV4Address, ip, 4);
- char *buffer = (char*) malloc(BUF_LEN * sizeof(char));
- asn_enc_rval_t er;
- //кодируем и пишем в файл
- er = der_encode_to_buffer(&asn_DEF_LogRecord, &rec, buffer,
- BUF_LEN);
- if (er.encoded == -1) {
- perror("cannot encode" SYMBOL(__LINE__));
- ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_LogRecord, &rec);
- return;
- }
- int len = er.encoded;
- fwrite(&len, sizeof(len), 1, log);
- fwrite(buffer, sizeof(char), len, log);
- free(buffer);
- ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_LogRecord, &rec);
- } else if (req->present == Request_PR_get) {
- resp = (Response_t *) calloc(1, sizeof(Response_t));
- resp->present = Response_PR_NOTHING;
- //получаем размер файла
- fseek(log, 0, SEEK_END);
- int len, endpos = ftell(log);
- //перемещаемся в начало
- fseek(log, 0, 0);
- while (ftell(log) != endpos) {
- //считываем размер закодированного блока и сам блок
- fread(&len, sizeof(len), 1, log);
- char *buffer = (char*) malloc(len * sizeof(char));
- fread(buffer, sizeof(char), len, log);
- LogRecord_t *tmp = nullptr;
- asn_dec_rval_t rv;
- //декодируем
- rv = ber_decode(0, &asn_DEF_LogRecord, (void**) &tmp, buffer, len);
- if (rv.code != RC_OK) {
- perror("cannot decode" SYMBOL(__LINE__));
- ASN_STRUCT_FREE(asn_DEF_LogRecord, tmp);
- continue;
- }
- //проверяем
- if (check_record_get(tmp, req->choice.get)) {
- resp->present = Response_PR_records;
- asn_sequence_add(&resp->choice.records.list, tmp);
- } else
- ASN_STRUCT_FREE(asn_DEF_LogRecord, tmp);
- free(buffer);
- }
- } else if (req->present == Request_PR_clear) {
- if (req->choice.clear.present == ClearRequest_PR_all) {
- //пересоздаем файл, если удаляем все
- fflush(log);
- fclose(log);
- log = fopen(F_NAME, "wb+");
- } else {
- //получаем размер файл
- fseek(log, 0, SEEK_END);
- int len, endpos = ftell(log);
- //идем в начало
- fseek(log, 0, 0);
- while (ftell(log) != endpos) {
- //считываем длину блока и сам блок
- fread(&len, sizeof(len), 1, log);
- char *buffer = (char*) malloc(len * sizeof(char));
- fread(buffer, sizeof(char), len, log);
- LogRecord_t *tmp = nullptr;
- asn_dec_rval_t rv;
- //декодируем
- rv = ber_decode(0, &asn_DEF_LogRecord, (void**) &tmp, buffer,
- len);
- if (rv.code != RC_OK) {
- perror("cannot decode" SYMBOL(__LINE__));
- ASN_STRUCT_FREE(asn_DEF_LogRecord, tmp);
- continue;
- }
- //проверяем
- if (!check_record_clear(tmp, req->choice.clear)) {
- //перемещаемся в файл к началу блок, чтоб не упустить его
- fseek(log, -(len * sizeof(char) + sizeof(len)), SEEK_CUR);
- ASN_STRUCT_FREE(asn_DEF_LogRecord, tmp);
- free(buffer);
- break;
- }
- ASN_STRUCT_FREE(asn_DEF_LogRecord, tmp);
- free(buffer);
- }
- if (ftell(log) == endpos) {
- //на случай если удалить надо все
- fflush(log);
- fclose(log);
- log = fopen(F_NAME, "wb+");
- } else {
- //копируем остаток файл в другой, а потом переименовываем
- FILE *log2 = fopen(F_NAME ".tmp", "wb+");
- int cpsize = endpos - ftell(log);
- char *buffer = (char*) malloc(cpsize * sizeof(char));
- fread(buffer, sizeof(char), cpsize, log);
- fwrite(buffer, sizeof(char), cpsize, log2);
- fclose(log);
- fclose(log2);
- remove(F_NAME);
- rename(F_NAME ".tmp", F_NAME);
- log = fopen(F_NAME, "ab+");
- free(buffer);
- }
- }
- }
- }
- struct buf_data {
- int size;
- int pos;
- char *buffer;
- };
- int buf_write(const void *buffer, size_t size, void *app_key) {
- buf_data *data = (buf_data*)app_key;
- data->pos += size;
- if(data->pos > data->size) {
- data->buffer = (char*)realloc(data->buffer, data->size *= 2);
- }
- memcpy(data->buffer + (data->pos - size), buffer, size);
- return 0;
- }
- int main(void)
- {
- socklen_t client_len;
- int rc, on = 1;
- int listen_sd = -1, new_sd = -1, client_sock;
- int end_server = FALSE, compress_array = FALSE;
- int close_conn;
- struct sockaddr_in addr, client_addr;
- int timeout;
- struct pollfd fds[200];
- int nfds = 1, current_size = 0, i, j;
- listen_sd = socket(AF_INET, SOCK_STREAM, 0);
- bool flag = false;
- if (listen_sd >= 0) {
- rc = setsockopt(listen_sd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));
- if (rc >= 0) {
- rc = ioctl(listen_sd, FIONBIO, (char *)&on);
- if (rc >= 0 ) {
- addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY);
- addr.sin_port = htons(SERVER_PORT); rc = bind(listen_sd,(struct sockaddr *)&addr, sizeof(addr));
- if ( rc >= 0 ) {
- rc = listen(listen_sd, 32);
- if ( rc >= 0 ) {
- timeout = (3 * 60 * 1000);
- fds[0].events = POLLIN;
- fds[0].fd = listen_sd;
- flag = true;
- }
- }
- }
- }
- }
- if (!flag) {
- perror("fail");
- return -1;
- }
- FILE *log = fopen(F_NAME, "ab+");
- std::map<int, sockaddr_in> clients;
- //прослушка
- //цикл ожиданий
- do
- {
- printf("download...\n");
- rc = poll(fds, nfds, timeout);
- if (rc == 0 || rc < 0)
- {
- printf(rc == 0 ? " timed out. End program.\n" : "fail" );
- break;
- }
- //ищем сигнал
- current_size = nfds;
- for (i = 0; i < current_size; i++)
- {
- if (fds[i].revents == 0)
- continue;
- //обработка случая, когда сервак можешь свалиться
- if (fds[i].revents != POLLIN)
- {
- printf(" Error! revents = %d\n", fds[i].revents);
- end_server = TRUE;
- break;
- }
- if (fds[i].fd == listen_sd)
- {
- printf(" Listening socket is readable\n");
- client_len = sizeof(sockaddr);
- client_sock = new_sd = accept(listen_sd, (sockaddr *) &client_addr,
- &client_len);
- clients[client_sock] = client_addr;
- printf(" New incoming connection - %d\n", new_sd);
- fds[nfds].fd = new_sd;
- fds[nfds].events = POLLIN;
- nfds++;
- }
- //для отправок и приемов
- else {
- printf(" Descriptor %d is readable\n", fds[i].fd);
- close_conn = FALSE;
- uint32_t len;
- int n, sock = fds[i].fd;
- //получаем длину блока и проверяем на отключение
- n = recvn(sock, &len, sizeof(len));
- if ( n <= 0 ) {
- continue;
- }
- len = ntohl(len);
- char *buffer = (char*) malloc(sizeof(char) * len);
- //получаем сам блок
- n = recvn(sock, buffer, len);
- if ( n <= 0 ) {
- continue;
- }
- asn_dec_rval_t rv;
- Request_t *req = nullptr;
- rv = ber_decode(0, &asn_DEF_Request, (void**) &req, buffer,
- len);
- if(rv.code != RC_OK) {
- perror("decode");
- ASN_STRUCT_FREE(asn_DEF_Request, req);
- free(buffer);
- return 1;
- }
- free(buffer);
- Response_t *resp = nullptr;
- //обрабатываем
- process_request(req, resp, log, clients[sock]);
- if (resp != nullptr) {
- asn_enc_rval_t er;
- buf_data data;
- data.buffer = (char*)malloc(sizeof(char) * 1024);
- data.size = 1024;
- data.pos = 0;
- er = der_encode(&asn_DEF_Response, resp, buf_write, &data);
- //отправляем длину блока и сам блок
- if (er.encoded == -1) {
- printf("%s ", er.failed_type->name);
- perror("encode" SYMBOL(__LINE__));
- } else {
- uint32_t len = er.encoded;
- len = htonl(len);
- if (send(sock, &len, sizeof(len), 0) < 0) {
- perror("send");
- free(data.buffer);
- return 1;
- }
- len = ntohl(len);
- if (send(sock, data.buffer, len, 0) < 0) {
- perror("send");
- free(data.buffer);
- return 1;
- }
- }
- free(data.buffer);
- }
- ASN_STRUCT_FREE(asn_DEF_Request, req);
- ASN_STRUCT_FREE(asn_DEF_Response, resp);
- }
- if (close_conn)
- {
- close(fds[i].fd);
- fds[i].fd = -1;
- compress_array = TRUE;
- }
- }
- if (compress_array)
- {
- compress_array = FALSE;
- for (i = 0; i < nfds; i++)
- {
- if (fds[i].fd == -1)
- {
- for (j = i; j < nfds; j++)
- {
- fds[j].fd = fds[j + 1].fd;
- }
- nfds--;
- }
- }
- }
- } while (end_server == FALSE);
- for (i = 0; i < nfds; i++)
- {
- if (fds[i].fd >= 0)
- close(fds[i].fd); //сворачиваемся
- }
- }
Add Comment
Please, Sign In to add comment