/
trilirium
/
Archived_BLC
Обзор
Документация
Войти
/
trilirium
/
Archived_BLC
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
Network.cpp
329 строк
7 KB
Trilirium
repo created OK
22 янв 2026, 16:43
22 янв 2026, 16:43
f05d14b
Код
Авторство
О чём код?
/* + === - === - === - === - === - === - === - === | | Network.cpp: | | Basic networking interface | + === - === - === - === - === - === - === - === */ #include <fcntl.h> #include <winsock.h> #include <wininet.h> #include <stdlib.h> // Get error code: unsigned get_errno () { return (errno); } // Network connection struct Connection { int sd; int s_errno; // Connection constructor (client side) Connection () { sd = socket (AF_INET, SOCK_STREAM, 0); if (sd < 0) s_errno = get_errno (); } // Connection constructor (client side) Connection (int sd) { this->sd = sd; s_errno = 0; } // Connection constructor (server side) Connection (unsigned IP_addr, unsigned port_no) { struct sockaddr_in sock_addr; sd = socket (AF_INET, SOCK_STREAM, 0); if (sd >= 0) { memset ((char *) &sock_addr, 0, sizeof(sock_addr)); sock_addr.sin_family = AF_INET; sock_addr.sin_addr.s_addr = IP_addr; sock_addr.sin_port = htons(port_no); if (bind (sd, (struct sockaddr *) &sock_addr, sizeof (sock_addr)) < 0) s_errno = get_errno (); } else s_errno = get_errno (); } // Connection // Server only: listen to socket (with backlog) int listen (unsigned backlog) { return ::listen (sd, backlog); } // listen // Server only: accept client connection Connection * accept () { struct sockaddr_in client_addr; int client_len = sizeof(client_addr); int client_sd = ::accept(sd, (struct sockaddr *) &client_addr, &client_len); if (client_sd >= 0) return new Connection (client_sd); return 0; } // accept // Client only: connect to server int connect (unsigned IP_addr, unsigned port_no) { int result; struct sockaddr_in serv_addr; memset ((char *) &serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = IP_addr; serv_addr.sin_port = htons(port_no); if ((result = ::connect (sd, (struct sockaddr *) &serv_addr, sizeof(serv_addr))) < 0) s_errno = get_errno (); return result; } // connect // // Close I/O subsystem // (return true on success) // bool close () { ::close (sd); return true; } // close // Read from input stream ('in_count' bytes) to 'in_buf' // (== receive data from socket) int read (void *in_buf, unsigned in_count) { // (receive data from socket) int count = recv (sd, (char *)in_buf, in_count, 0); if (count < 0) s_errno = get_errno (); return count; } // read // Write to output stream ('out_count' bytes) from 'out_buf' // (== transmit data to socket) int write (const void *out_buf, unsigned out_count) { // (send data to socket) int count = send (sd, (const char *)out_buf, out_count, 0); if (count < 0) s_errno = get_errno (); return count; } // write // Put single octet to stream bool put_octet (char octet) { return write (&octet, 1) == 1; } // put_octet // Get single octet from stream bool get_octet (char &octet) { return read (&octet, 1) == 1; } // get_octet // Output C-string in sequence Connection &out_cstr (char const *str) { unsigned len = strlen (str); bool result = write (str, len) == len; return *this; } // out_cstr // Output label in sequence Connection &out_label (char const *str) { out_cstr (str); put_octet (' '); return *this; } // out_cstr // Output EOL in sequence Connection &out_nl () { return out_cstr ("\r\n"); return *this; } // out_nl // Sync bool sync () { return true; } // // Read chars until 'brk_ch' // Result: // 1: break char reached // -1: end of file reached // 0: buffer filled // int read_buffer_until (char *buffer, unsigned &buf_size, char brk_ch) { unsigned i = 0; char ch; while (i != buf_size) { if (get_octet (ch)) if (ch == brk_ch) { buf_size = i; return 1; } else buffer [i ++] = ch; else { buf_size = i; return -1; } } return 0; } // read_buffer_until enum { Init_BufSize = 256 }; // Read string until 'brk_ch' // Returns buffer char const * read_string_until (char brk_ch) { char InBuf [Init_BufSize]; // (initial buffer) int result; // Read text record struct InRec { char *buffer; // (stored char data) unsigned len; // (length of stored char data) InRec *prev; // (previous buffer in chain) } _Init, *_last; _Init.buffer = InBuf; _Init.len = sizeof(InBuf); _Init.prev = 0; _last = &_Init; // (reading from input) while ((result = read_buffer_until (_last->buffer, _last->len, brk_ch)) == 0) { // allocate & chain input buffers struct InRec *new_rec = new ("Input/Record") InRec; new_rec->buffer = new ("Input/Buffer") char [new_rec->len = (_last->len / 2) * 3]; new_rec->prev = _last; _last = new_rec; } if (result == 1) { // (done reading -- calculate total length) struct InRec *rec; unsigned length = 0; for (rec = _last; rec; rec = rec->prev) length += rec->len; // (allocate & copy characters) char *data = new ("read_buffer") char [length + 1]; data += length; *data = '\0'; while (rec = _last) { data -= rec->len; memcpy (data, rec->buffer, rec->len); if (_last = rec->prev) { delete [] rec->buffer; delete rec; } } // (while) return data; } return 0; // (read failed!) } // read_string_until // Read from file & transmit data over network bool read_transmit (File_Input &file_transmit, unsigned length) { enum { TransmitLen = 1024 }; char buffer [TransmitLen]; int amount; while (amount = length) { if (amount > TransmitLen) amount = TransmitLen; if ((amount = file_transmit.read (buffer, amount)) < 0) return false; // (file read fail) if (amount) { if (write (buffer, amount) != amount) return false; // (network transmit fail) length -= amount; } } // while (length) return true; // (success) } // read_transmit // Receive data over network & write to file bool write_receive (File_Output &file_receive, unsigned length) { enum { ReceiveLen = 1024 }; char buffer [ReceiveLen]; int amount; while (amount = length) { if (amount > ReceiveLen) amount = ReceiveLen; if ((amount = read (buffer, amount)) < 0) return false; // (network receive fail) if (amount) { if ((file_receive.write (buffer, amount)) != amount) return false; // (file write fail) length -= amount; } } // while (length) return true; // (success) } // write_receive }; // Connection // Get host by name unsigned host_by_name (char const *host_name) { struct hostent *server = gethostbyname (host_name); struct in_addr addr; if (server) { memcpy (&addr, server->h_addr_list[0], server->h_length); return addr.S_un.S_addr; } return 0; // (no host) } // host_by_name // // Init/term sockets // static bool sockets_ready = false; // Initialize sockets I/O bool init_sockets () { if (! sockets_ready) { struct WSAData data; if (WSAStartup (0x101, &data) == SOCKET_ERROR) return false; return true; } return true; } // init_sockets // Terminate sockets I/O bool term_sockets () { if (sockets_ready) WSACleanup (); return true; } // term_sockets