doc_and_tools/tools/sdk/include/net/net_app.h

260 lines
16 KiB
C++

// net_app.h : network applications
//
// Author: Gongbing
//
// Create: 2019-07-22
#pragma once
#include "net_base.h"
//typedef struct ip_option_information {
// UCHAR Ttl;
// UCHAR Tos;
// UCHAR Flags;
// UCHAR OptionsSize;
// PUCHAR OptionsData;
//} IP_OPTION_INFORMATION, *PIP_OPTION_INFORMATION;
//typedef struct icmp_echo_reply {
// struct sockaddr_in Address;
// ULONG Status;
// ULONG RoundTripTime;
// USHORT DataSize;
// USHORT Reserved;
// PVOID Data;
// struct ip_option_information Options;
//} ICMP_ECHO_REPLY, *PICMP_ECHO_REPLY;
//#define IPAddr struct sockaddr_in
namespace net_app
{
enum web_format
{
WEB_FMT_UNKNOWN = 0,
WEB_FMT_STREAM, // binary stream ...
WEB_FMT_ANSI,
WEB_FMT_UTF8,
WEB_FMT_UNICODE,
WEB_FMT_DECIDE_BY_CONTENT, // text/html should decide by content
};
__declspec(novtable) struct IAcceptClient : public ref_util::IRef
{
COM_API_DECLARE(long, client_accepted(SOCKET s, const char* ip, unsigned port));
COM_API_DECLARE(void, on_server_exited(unsigned exit_code));
};
__declspec(novtable) struct ITcpSvrSocket : public ref_util::IRef
{
COM_API_DECLARE(long, listen_at(unsigned short port, const char* ip = NULL/*INADDR_ANY*/, bool reuse_addr = true));
COM_API_DECLARE(long, stop(void));
COM_API_DECLARE(long, listen_port(void));
COM_API_DECLARE(SOCKET, listen_socket(void));
};
__declspec(novtable) struct IAsyncTcpSvr : public ITcpSvrSocket
{
// following two functions return ERROR_FILE_HANDLE_REVOKED if the peer is used in transmit file
COM_API_DECLARE(long, read_from_peer(void* peer_key)); // DO NOT call this until you stop the read with return -1 in IPeerManager::on_data_arrived, server will invoke this automately
COM_API_DECLARE(long, write_2_peer(void* peer_key, const char* data, size_t data_len, bool inner_buffer = false/*whether the data buffer is returned by request_sent_buffer, if failed and iner_buffer is 'true', the 'data' would be freed !!!*/));
COM_API_DECLARE(long, close_peer(void* peer_key, int* peer_ref));
COM_API_DECLARE(long, set_peer_data(void* peer_key, int index, void* data));
COM_API_DECLARE(long, get_peer_data(void* peer_key, int index, void** data));
COM_API_DECLARE(long, peer_address(void* peer_key, char ip_buf[IP_BUF_LEN], unsigned* port));
COM_API_DECLARE(long, send_file_content(void* peer_key, HANDLE file)); // NOTE: this method only used for transmitting file content, all pre- or post-task should done by caller !!!
COM_API_DECLARE(size_t, io_buffer_size(bool in_buf));
// add on 2017-08-26 for add an existing connecting into client queue (DO NOT add it which is already in queue !!!)
// after this, you should operate the peer in IPeerManager.
// following two apis return peer_key
COM_API_DECLARE(void*, add_2_client_queue(SOCKET s));
COM_API_DECLARE(void*, create_async_tcp_client(const char* ip, unsigned short port, unsigned conn_timeout_seconds = 0, const char* reuse_ip = NULL, unsigned reuse_port = 0));
// for reducing the times of memory copying, request memory from inner - added on 2019-07-28
COM_API_DECLARE(char*, request_sent_buffer(size_t bytes));
COM_API_DECLARE(void, free_unsent_buffer(void* buf)); // free the returned value of request_sent_buffer which has NOT called write_2_peer with inner_buffer is 'true' yet!!!
};
__declspec(novtable) struct IAsyncTcpHatcher : public ref_util::IRef
{
COM_API_DECLARE(void*, connect(const char* ip, int port, const char* reuse_ip = NULL, unsigned reuse_port = 0));
COM_API_DECLARE(int, write(void* client, const char* buf, size_t data_len, bool inner_buf));
//COM_API_DECLARE(void*, add_2_client_queue(SOCKET s));
COM_API_DECLARE(int, close_client(void* client));
COM_API_DECLARE(int, destroy(void));
COM_API_DECLARE(long, send_file_content(void* client, HANDLE file)); // NOTE: this method only used for transmitting file content, all pre- or post-task should done by caller !!!
COM_API_DECLARE(bool, get_address(void* client, char* ip/*at least with 40 bytes!!!*/, int* port, bool svr = true));
};
__declspec(novtable) struct IAsyncTcpHandler : public ref_util::IRef
{
COM_API_DECLARE(long, on_data_arrived(void* client, const char* data, size_t data_len, bool* rcv_file/*[in] - whether in receiving file for transmit_file, [out] - stop(true) or continue(true) receiving file*/)); // return how many bytes used, -1 to stop receiving !!!
COM_API_DECLARE(bool, on_data_sent(void* client, char* data, size_t data_len, size_t data_buf_len/*for reuse inner_buffer*/)); // return whether to keep the data buffer in use. true - use again, false - default value, should free it
COM_API_DECLARE(void, on_closed(void* client, int err));
COM_API_DECLARE(void, on_file_content_sent(void* client, HANDLE file, ULONGLONG bytes, int error)); // response for IAsyncTcpSvr::send_file_content
};
__declspec(novtable) struct IPeerManager : public ref_util::IRef
{
COM_API_DECLARE(void, on_peer_connected(void* peer_key));
COM_API_DECLARE(void, on_server_exited(unsigned exit_code));
COM_API_DECLARE(long, on_data_arrived(void* peer_key, const char* data, size_t data_len, bool* rcv_file/*[in] - whether in receiving file for transmit_file, [out] - stop(true) or continue(true) receiving file*/)); // return how many bytes used, -1 to stop receiving !!!
COM_API_DECLARE(bool, on_data_sent(void* peer_key, char* data, size_t data_len, size_t data_buf_len/*for reuse inner_buffer*/)); // return whether to keep the data buffer in use. true - use again, false - default value, should free it
COM_API_DECLARE(void, on_peer_error(void* peer_key, unsigned err_code));
COM_API_DECLARE(void, on_peer_closed(void* peer_key));
COM_API_DECLARE(bool, is_peer_timeout(void* peer_key, int elapsed_seconds/*elapsed seconds from last active*/));
COM_API_DECLARE(void, on_file_content_sent(void* peer_key, HANDLE file, ULONGLONG bytes, int error)); // response for IAsyncTcpSvr::send_file_content
};
__declspec(novtable) struct IBlockTcp : public ref_util::IRef
{
COM_API_DECLARE(SOCKET, attach(SOCKET s));
COM_API_DECLARE(SOCKET, detach(void));
COM_API_DECLARE(SOCKET, socket_handle(void));
COM_API_DECLARE(int, re_connect(const char* dot_ip = NULL, unsigned short port = 0));
COM_API_DECLARE(int, set_timeout(unsigned *read_timeout/*milliseconds*/, unsigned *write_timeout/*milliseconds*/));
COM_API_DECLARE(int, read(char* buf, size_t buf_len, size_t* read_bytes));
COM_API_DECLARE(int, write(const char* buf, size_t data_len, size_t* wrote));
COM_API_DECLARE(int, last_error(void));
COM_API_DECLARE(long, send_file_content(HANDLE file)); // NOTE: this method only used for transmitting file content, all pre- or post-task should done by caller !!!
COM_API_DECLARE(void, get_address(char* ip/*at least with 40 bytes!!!*/, int* port, bool svr = true));
COM_API_DECLARE(int, close(void));
};
__declspec(novtable) struct IUdpSvrHandler : public ref_util::IRef
{
COM_API_DECLARE(size_t,on_udp_data_arrived(const char* data, size_t data_len, const char* ip, unsigned port)); // return used data bytes
COM_API_DECLARE(bool, on_udp_data_sent(char* data, size_t data_len, size_t data_buf_len/*for reuse inner_buffer*/, const char* ip, unsigned port)); // return whether to keep the data buffer in use. true - use again, false - default value, should free it
COM_API_DECLARE(void, on_udp_server_exit(unsigned err));
};
__declspec(novtable) struct IUdpServer : public ref_util::IRef
{
COM_API_DECLARE(int, start(unsigned short port));
COM_API_DECLARE(int, send_to(const char* buf, size_t len, const char* ip, unsigned port, bool inner_buffer = false/*whether the data buffer is returned by request_sent_buffer*/));
COM_API_DECLARE(int, broad_cast(const char* buf, size_t len, unsigned short port, bool inner_buffer = false, const char* broad_ip_seg = NULL));
COM_API_DECLARE(int, stop(void));
// for reducing the times of memory copying, request memory from inner - added on 2019-07-28
COM_API_DECLARE(char*, request_sent_buffer(size_t bytes));
COM_API_DECLARE(void, free_unsent_buffer(void* buf)); // free the returned value of request_sent_buffer which has NOT called write_2_peer with inner_buffer is 'true' yet!!!
};
typedef struct _set_cookie // all members and its' buffers will be in the same buffer with the head
{
char *name;
char *val;
char *path;
char *expire;
char *domain;
bool http_only;
bool https_only; // true - secure 1; false - secure 0
}SETCOOKIE, *LPSETCOOKIE;
enum _add_head_flag
{
ADD_HEAD_ADD = 1, // new item added if the key was not existing, or else failed
ADD_HEAD_NEW, // new item added however the key is existing already
ADD_HEAD_REPLACE, // new item added if the key was not existing, or else replace it with new val
ADD_HEAD_APPEND_COMMA, // like ADD_HEAD_REPLACE but append new val to rear with comma(,) if the key was existing
ADD_HEAD_APPEND_SEMIC, // like ADD_HEAD_REPLACE but append new val to rear with semicolon(;) if the key was existing
};
enum _cookie_index
{
COOKIE_INDEX_ALL = -1,
};
#ifdef _USE_HTTP_CALLBACK_
__declspec(novtable) struct IHttpCallback : public ref_util::IRef
{
COM_API_DECLARE(void, on_response_header_ok(int response_code, unsigned __int64 cont_len, bool cont_chunked, bool cont_zipped));
COM_API_DECLARE(int, on_response_content(const char* content, size_t len)); // return 0 to continue, other to stop
COM_API_DECLARE(int, on_url_jump(int jump_code, const char* utf8_new_url)); // return 0 to continue, other to stop
};
#endif
__declspec(novtable) struct IHttp : public ref_util::IRef // all methods are thread unsafe, all history cookies will occur in last request
{
#ifndef _USE_HTTP_CALLBACK_
COM_API_DECLARE(void, set_response_data_callback(inter_module_data::set_data setdata, void* param));
#endif
COM_API_DECLARE(int, add_header(const char* utf8_key, const char* utf8_val, _add_head_flag flag = ADD_HEAD_REPLACE)); // 0 - ok; ERROR_ALREADY_EXISTS. must call before open_url or post_data
COM_API_DECLARE(int, remove_header(const char* utf8_key/*NULL to clear all extra headers*/)); // 0 - ok; ERROR_NOT_FOUND. must call before open_url or post_data
COM_API_DECLARE(int, clear_cookie(void)); // all history cookies would be added on the last request, call this to clear all cookies
COM_API_DECLARE(int, open_url(const char* url, const char* cookie, const char* agent, bool get = true, const char* content = NULL, size_t content_len = 0));
COM_API_DECLARE(int, post_data(const char* url, const char* data, unsigned __int64 data_len, const char* utf8_file_tag, const char* utf8_file_name, const char* cookie, const char* agent));
COM_API_DECLARE(int, get_response_code(void));
COM_API_DECLARE(int, get_set_cookie(LPSETCOOKIE buf/*format: cookie1\0cookie2\0\0*/, size_t* len/*[in] - bytes of buf, [out] - string length in buf or minimum buffer size if buf was NULL*/
, int index = 0/*if index == COOKIE_INDEX_ALL, then return all cookies in ONE string and put it in buf*/)); // 0 - ok; ERROR_NOT_FOUND
COM_API_DECLARE(int, get_jump_url(char* buf, size_t* len/*[in] - bytes of buf, [out] - string length in buf or minimum buffer size if buf was NULL*/)); // 0 - ok; ERROR_NOT_FOUND
COM_API_DECLARE(int, get_response_all_header(char* buf, size_t* len/*[in] - bytes of buf, [out] - string length in buf or minimum buffer size if buf was NULL*/)); // 0 - ok; ERROR_NOT_FOUND
COM_API_DECLARE(unsigned __int64, get_response_content_length(void));
COM_API_DECLARE(enum web_format, get_content_format(void));
COM_API_DECLARE(void, close(void));
};
PORT_API(ITcpSvrSocket*) create_tcp_server_socket(IAcceptClient* ac, bool ipv6 = false);
enum _svr_ip_type
{
SVR_TYPE_NONE = 0,
SVR_TYPE_IPV4_ONLY = 1,
SVR_TYPE_IPV6_ONLY,
SVR_TYPE_IPV4_AND_IPV6,
};
PORT_API(IAsyncTcpSvr*) create_async_tcp_server(IPeerManager* peer, _svr_ip_type svr_type = SVR_TYPE_IPV4_ONLY, int buf_size_in = 0, int buf_size_out = 0, int desired_threads = 0, unsigned allow_cpu_mask = -1);
// for blocking tcp would blocks following operation, this function will set r/w timeout to be 9 seconds;
PORT_API(IBlockTcp*) connect_2_server(const char* ip, unsigned short port, unsigned conn_timeout_seconds = 0, const char* reuse_ip = NULL, unsigned reuse_port = 0);
PORT_API(IBlockTcp*) connect_2_server_by_host(const char* host, unsigned short port, unsigned conn_timeout_seconds = 0, const char* reuse_ip = NULL, unsigned reuse_port = 0);
PORT_API(IAsyncTcpHatcher*) create_async_tcp_hatcher(IAsyncTcpHandler* handler);
PORT_API(IUdpServer*) create_udp_server(IUdpSvrHandler* handler, _svr_ip_type type = SVR_TYPE_IPV4_ONLY);
#ifdef _USE_HTTP_CALLBACK_
PORT_API(IHttp*) create_http(IHttpCallback* cb);
#else
PORT_API(IHttp*) create_http(void);
#endif
// trace route by ICMPxxx function, to be completed ...
// parameter of result:
// data: ip, NULL when over
// len: milliseconds, -1 is timeout, or error code when over
// total: hops count, unused when over
// flag: DATA_FLAG_FINAL in hops, DATA_FLAG_INSTAR in beginning information, and DATA_FLAG_OVER for over
// param: 'param'
PORT_API(int) trace_route(const char* www, inter_module_data::set_data result, void* param, int max_hops = 30);
PORT_API(int) get_default_gateway(char gateway[IP_BUF_LEN]);
PORT_API(int) get_mac(const char* dot_ip, char *mac, int* mac_bytes/*in - bytes of 'mac', out - result bytes in 'mac'*/);
// enum all ips in given subnet ...
// parameter of result:
// data: ip, NULL when over
// len: bytes of 'data'
// total: unused
// flag: DATA_FLAG_FINAL
// param: same as 'param'
PORT_API(int) enum_all_ips_in_subnet(const char* dot_ip, const char* dot_subnet, inter_module_data::set_data result, void* param);
PORT_API(int) parse_cookie(const char* cookie_str, LPSETCOOKIE lpcookie, size_t size/*size of lpcookie must great than sizeof(SETCOOKIE) + lstrlenA(cookie_str) * 2*/);
PORT_API(int) cookie_for_url(LPSETCOOKIE lpcookie, const char* url, char* cookie, size_t* len);
PORT_API(int) http_post(const char* url, const char* content, size_t length, const char* utf8_file_tag, const char* utf8_file_name = NULL, const char* cookie = NULL, const char* agent = NULL);
PORT_API(int) http_download(const char* url, inter_module_data::set_data setdata, void* param, const char* cookie = NULL, const char* agent = NULL, const char* extra_data = 0, size_t extra_data_len = 0);
PORT_API(enum web_format) web_content_format(const char* web_cont, size_t bytes, UINT* cp = NULL/*to receive the code page*/);
// function: send file by 'TransmitFile' for more efficiency, the function is blocked until all content transfered or error happens if parameter 'lpovl' was NULL
// file: an openning file handle, suggest use flag with 'FILE_FLAG_SEQUENTIAL_SCAN'
// s: an connection socket
// packet_size: bytes of every packet
// lpovl: asynchronous OVERLAPPED data. if you bind the socket on an IOCP, the IOCP will receive a write complete notify
// pre: the content sent to remote before the file content
// pre_bytes: bytes of 'pre' content
// rear: the content sent to remote after all file contents transfered
// rear_bytes: bytes of 'rear' content
//
// return: error code.
PORT_API(int) transmit_file(HANDLE file, SOCKET s, size_t bytes_to_sent = 0/*max up to INT_MAX - 1*/, size_t packet_size = 4096, LPOVERLAPPED lpovl = NULL, void* pre = NULL, size_t pre_bytes = 0, void* rear = NULL, size_t rear_bytes = 0);
PORT_API(HANDLE) open_file_for_sending(const wchar_t* local_file);
enum
{
NIC_CHANGED = 0, // MibParameterNotification,
NIC_ADDED = 1, // MibAddInstance,
NIC_DELETED = 2, // MibDeleteInstance,
};
// parameter of notify:
// data: ip, this is the final ip
// len: index of network interface
// total_len: NIC_CHANGED - parameter changed; NIC_ADDED - new NIC added; NIC_DELETED - NIC deleted
// flag: be inter_module_data::DATA_FLAG_FINAL always
PORT_API(void*) reg_interface_notification(inter_module_data::set_data notify, void* param); // free the returned object by unreg_interface_notification
PORT_API(void) unreg_interface_notification(void* key/*returned by reg_interface_notification()*/);
}