-
Notifications
You must be signed in to change notification settings - Fork 4
/
uvx.c
145 lines (127 loc) · 4.55 KB
/
uvx.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <memory.h>
#include <assert.h>
#include <uv.h>
#include "utils/automem.h"
// Author: Liigo <liigo@qq.com>
const char* uvx_get_ip_port(const struct sockaddr* addr, char* ipbuf, int buflen, int* port) {
switch (addr->sa_family) {
case AF_INET: {
const struct sockaddr_in* addrin = (const struct sockaddr_in*) addr;
if(ipbuf) uv_inet_ntop(AF_INET, &(addrin->sin_addr), ipbuf, buflen);
if(port) *port = (int) ntohs(addrin->sin_port);
break;
}
case AF_INET6: {
const struct sockaddr_in6* addrin = (const struct sockaddr_in6*) addr;
if(ipbuf) uv_inet_ntop(AF_INET6, &(addrin->sin6_addr), ipbuf, buflen);
if(port) *port = (int) ntohs(addrin->sin6_port);
break;
}
default:
if(port) *port = 0;
return NULL;
}
return ipbuf ? ipbuf : NULL;
}
int uvx_get_raw_ip_port(const struct sockaddr* addr, unsigned char* ipbuf, int* port) {
switch (addr->sa_family) {
case AF_INET: {
const struct sockaddr_in* addrin = (const struct sockaddr_in*) addr;
if(ipbuf) memcpy(ipbuf, &addrin->sin_addr, sizeof(addrin->sin_addr));
if(port) *port = (int) ntohs(addrin->sin_port);
return sizeof(addrin->sin_addr); // 4
break;
}
case AF_INET6: {
const struct sockaddr_in6* addrin = (const struct sockaddr_in6*) addr;
if(ipbuf) memcpy(ipbuf, &addrin->sin6_addr, sizeof(addrin->sin6_addr));
if(port) *port = (int) ntohs(addrin->sin6_port);
return sizeof(addrin->sin6_addr); // 16
break;
}
default:
if(port) *port = 0;
return 0;
}
}
const char* uvx_get_tcp_ip_port(uv_tcp_t* uvclient, char* ipbuf, int buflen, int* port) {
struct sockaddr addr;
int len = sizeof(addr);
int r = uv_tcp_getpeername(uvclient, &addr, &len);
if(r == 0) {
return uvx_get_ip_port(&addr, ipbuf, buflen, port);
} else {
printf("\n!!! [uvx] get client ip failed: %s\n", uv_strerror(r));
return NULL;
}
}
static void uvx_after_send_to_stream(uv_write_t* w, int status) {
if(status) {
printf("\n!!! [uvx] uvx_send_to_stream() failed or canceled: %d\n", status);
}
//see uvx_send_to_stream()
free(w->data);
free(w);
}
// Note: after this call, do not use `data` anymore, its memory will be `free`ed later.
int uvx_send_to_stream(uv_stream_t* stream, void* data, unsigned int size) {
// puts("uvx_send_to_stream()\n");
assert(stream && data);
uv_buf_t buf = { .base = (char*)data, .len = (size_t)size };
uv_write_t* w = (uv_write_t*) malloc(sizeof(uv_write_t));
memset(w, 0, sizeof(uv_write_t));
w->data = data; // free it in uvx_after_send_to_stream()
return (uv_write(w, stream, &buf, 1, uvx_after_send_to_stream) == 0 ? 1 : 0);
}
static void uvx_after_send_mem(uv_write_t* w, int status) {
if(status) {
printf("\n!!! [uvx] uvx_send_mem() failed or canceled: %d\n", status);
}
//see uxv_send_mem()
automem_t mem;
mem.pdata = (unsigned char*)w->data;
automem_uninit(&mem);
free(w);
}
// Deprecated, use uvx_send_to_stream() instead.
// Note: after invoke uvx_send_mem(), do not use mem anymore, its memory will be freed later.
int uvx_send_mem(automem_t* mem, uv_stream_t* stream) {
// puts("uvx_send_mem()\n");
assert(mem && mem->pdata);
assert(stream);
uv_buf_t buf = { .base = (char*)mem->pdata, .len = (size_t)mem->size };
uv_write_t* w = (uv_write_t*) malloc(sizeof(uv_write_t));
memset(w, 0, sizeof(uv_write_t));
w->data = mem->pdata; // free it in after_send_mem()
return uv_write(w, stream, &buf, 1, uvx_after_send_mem);
}
//-----------------------------------------------------------------------------
// internal functions
void uvx__on_alloc_buf(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {
buf->base = (char*) malloc(suggested_size);
buf->len = buf->base ? suggested_size : 0;
}
/**
// vc2017 has builtin snprintf
#if defined(_WIN32) && !defined(__GNUC__)
#include <stdarg.h>
// Emulate snprintf() on Windows, _snprintf() doesn't zero-terminate the buffer on overflow...
int snprintf(char* buf, size_t len, const char* fmt, ...) {
va_list ap;
int n;
va_start(ap, fmt);
n = _vsprintf_p(buf, len, fmt, ap);
va_end(ap);
// It's a sad fact of life that no one ever checks the return value of
// snprintf(). Zero-terminating the buffer hopefully reduces the risk
// of gaping security holes.
if (n < 0)
if (len > 0)
buf[0] = '\0';
return n;
}
#endif
**/