├── p2p_transfer_tcp ├── p2p_transfer_peer │ ├── Makefile │ ├── log.c │ ├── log.h │ ├── p2p_transfer.c │ ├── p2p_transfer.h │ ├── p2p_transfer_peer │ └── p2p_transfer_peer.c └── p2p_transfer_server │ ├── Makefile │ ├── list.h │ ├── log.c │ ├── log.h │ ├── p2p_transfer.c │ ├── p2p_transfer.h │ ├── p2p_transfer_server │ └── p2p_transfer_server.c └── p2p_transfer_udp ├── p2p_transfer_peer ├── Makefile ├── log.c ├── log.h ├── p2p_transfer.c ├── p2p_transfer.h ├── p2p_transfer_peer.c └── p2p_transfer_udp_peer └── p2p_transfer_server ├── Makefile ├── list.h ├── log.c ├── log.h ├── p2p_transfer.c ├── p2p_transfer.h ├── p2p_transfer_server └── p2p_transfer_server.c /p2p_transfer_tcp/p2p_transfer_peer/Makefile: -------------------------------------------------------------------------------- 1 | all:p2p_transfer_peer 2 | 3 | p2p_transfer_peer:clean 4 | gcc -o p2p_transfer_peer -g -O0 -W -Wall -Werror p2p_transfer_peer.c p2p_transfer.c log.c -levent -lm -lpthread 5 | clean : 6 | -rm -f p2p_transfer_peer 7 | -------------------------------------------------------------------------------- /p2p_transfer_tcp/p2p_transfer_peer/log.c: -------------------------------------------------------------------------------- 1 | #include "log.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | static const char* LEVEL_NAMES[] = {"DEBUG", "INFO", "NOTICE", "WARN", "ERROR", "FATAL"}; 10 | 11 | static int enable_console = 1; 12 | static FILE *log_stream = NULL; 13 | static int log_level = EN_PRINT_INFO; 14 | 15 | int configure_log(int lvl, const char* file, int use_console) { 16 | FILE *stream = NULL; 17 | int res = 0; 18 | 19 | if (lvl > EN_PRINT_ERROR) 20 | lvl = EN_PRINT_ERROR; 21 | else if (lvl < EN_PRINT_DEBUG) 22 | lvl = EN_PRINT_DEBUG; 23 | log_level = lvl; 24 | enable_console = use_console; 25 | if (file != NULL) { 26 | stream = fopen(file, "a"); 27 | if (stream == NULL) { 28 | XL_DEBUG(EN_PRINT_ERROR, "error opening log file, err: %s", strerror(errno)); 29 | res = 1; 30 | } else { 31 | log_stream = stream; 32 | } 33 | } 34 | 35 | return res; 36 | } 37 | 38 | void destroy_log() 39 | { 40 | if (log_stream != NULL) 41 | { 42 | fclose(log_stream); 43 | } 44 | } 45 | 46 | void logging(int lvl, const char *file, const char *func, const int line, const char *fmt, ...) { 47 | va_list ap; 48 | char buffer[512], *ptr = buffer; 49 | int size, cap = 512; 50 | time_t ts; 51 | struct tm *tmp; 52 | 53 | if (lvl < log_level) { 54 | return; 55 | } 56 | 57 | ts = time(NULL); 58 | tmp = localtime(&ts); 59 | size = strftime(ptr, cap, "[%Y-%m-%d %H:%M:%S]", tmp); 60 | ptr += size; 61 | cap -= size; 62 | size = snprintf(ptr, cap, "[%6s][%s:%d][%s] ", 63 | LEVEL_NAMES[lvl], file, line, func); 64 | ptr += size; 65 | cap -= size; 66 | 67 | va_start(ap, fmt); 68 | size = vsnprintf(ptr, cap, fmt, ap); 69 | va_end(ap); 70 | 71 | *(ptr + size) = '\n'; 72 | *(ptr + size + 1) = '\0'; 73 | 74 | if (enable_console) { 75 | if (lvl >= EN_PRINT_WARN) { 76 | fputs(buffer, stderr); 77 | } else { 78 | fputs(buffer, stdout); 79 | } 80 | } 81 | 82 | if (log_stream != NULL) { 83 | fputs(buffer, log_stream); 84 | fflush(log_stream); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /p2p_transfer_tcp/p2p_transfer_peer/log.h: -------------------------------------------------------------------------------- 1 | #ifndef __LOG_H_ 2 | #define __LOG_H_ 3 | 4 | enum _log_level { 5 | EN_PRINT_DEBUG, 6 | EN_PRINT_INFO, 7 | EN_PRINT_NOTICE, 8 | EN_PRINT_WARN, 9 | EN_PRINT_ERROR, 10 | EN_PRINT_FATAL, 11 | }; 12 | 13 | int configure_log(int level, const char* file, int use_console); 14 | void destroy_log(); 15 | 16 | void logging(int lvl, const char *file, const char *func, const int line, const char *fmt, ...); 17 | 18 | #define XL_DEBUG(lvl, fmt, ...) logging(lvl, __FILE__, __FUNCTION__, __LINE__, fmt, ##__VA_ARGS__) 19 | 20 | #endif /* __LOG_H_ */ 21 | -------------------------------------------------------------------------------- /p2p_transfer_tcp/p2p_transfer_peer/p2p_transfer.c: -------------------------------------------------------------------------------- 1 | #include "p2p_transfer.h" 2 | #include "log.h" 3 | #include 4 | #include 5 | 6 | const char *get_string_network_type(int network_type) 7 | { 8 | static char *s_network_type[] = { 9 | "UNKNOWN", 10 | "PUBLIC_NETWORK", 11 | "FULL_CONE_NAT", 12 | "RESTRICTED_CONE_NAT", 13 | "PORT_RESTRICTED_CONE_NAT", 14 | "SYMMETRIC_NAT", 15 | }; 16 | if (network_type < NP_UNKNOWN || network_type > NP_SYMMETRIC_NAT) 17 | { 18 | network_type = NP_UNKNOWN; 19 | } 20 | return s_network_type[network_type]; 21 | } 22 | 23 | int set_sock_opt(int sock, int flag) 24 | { 25 | int enable = 1; 26 | 27 | if (flag & SO_REUSEADDR) 28 | { 29 | if (-1 == setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable))) 30 | { 31 | XL_DEBUG(EN_PRINT_ERROR, "call setsockopt() failed, set SO_REUSEADDR failed, err: %s", strerror(errno)); 32 | return -1; 33 | } 34 | } 35 | if (flag & SO_REUSEPORT) 36 | { 37 | if (-1 == setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(enable))) 38 | { 39 | XL_DEBUG(EN_PRINT_ERROR, "call setsockopt() failed, set SO_REUSEPORT failed, err: %s", strerror(errno)); 40 | return -1; 41 | } 42 | } 43 | if (flag & SO_KEEPALIVE) 44 | { 45 | if (-1 == setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable))) 46 | { 47 | XL_DEBUG(EN_PRINT_ERROR, "call setsockopt() failed, set SO_KEEPALIVE failed, err: %s", strerror(errno)); 48 | return -1; 49 | } 50 | } 51 | return 0; 52 | } -------------------------------------------------------------------------------- /p2p_transfer_tcp/p2p_transfer_peer/p2p_transfer.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zhangli88/p2p_punch_hole/32fc7f58d921cdebad588e797c6159f890228ad1/p2p_transfer_tcp/p2p_transfer_peer/p2p_transfer.h -------------------------------------------------------------------------------- /p2p_transfer_tcp/p2p_transfer_peer/p2p_transfer_peer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zhangli88/p2p_punch_hole/32fc7f58d921cdebad588e797c6159f890228ad1/p2p_transfer_tcp/p2p_transfer_peer/p2p_transfer_peer -------------------------------------------------------------------------------- /p2p_transfer_tcp/p2p_transfer_peer/p2p_transfer_peer.c: -------------------------------------------------------------------------------- 1 | //#include "xl_common.h" 2 | #include "log.h" 3 | #include "p2p_transfer.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #define P2P_TRANSFER_LISTEN_MAX_NUM (16) 23 | 24 | #define P2P_TRANSFER_CLIENT_PORT (5152) 25 | 26 | struct p2p_transfer_client_t 27 | { 28 | struct event_base *base; 29 | uint64_t device_sn; 30 | 31 | struct event *puser_event; 32 | 33 | uint32_t local_ip; 34 | 35 | int conn_server_sock; 36 | struct event *pping_event; 37 | struct bufferevent *pping_bev; 38 | 39 | int listen_lcoal_sock; 40 | struct evconnlistener *listener; 41 | }; 42 | 43 | static struct p2p_transfer_client_t *s_ppt_client = NULL; 44 | 45 | static void listener_cb(UNUSED struct evconnlistener *listener, UNUSED evutil_socket_t conn_sock, 46 | UNUSED struct sockaddr *client_addr, UNUSED int socklen, UNUSED void *user_data) 47 | { 48 | XL_DEBUG(EN_PRINT_DEBUG, "listener_cb ..."); 49 | } 50 | 51 | void ping_cb(UNUSED evutil_socket_t sock, UNUSED short events, UNUSED void *user_data) 52 | { 53 | XL_DEBUG(EN_PRINT_DEBUG, "ping..."); 54 | 55 | struct p2p_msg_head_t *pmsg = NULL; 56 | struct p2p_msg_ping_t *pping = NULL; 57 | int total_len = sizeof(struct p2p_msg_head_t) + sizeof(struct p2p_msg_ping_t); 58 | 59 | SAFE_CALLOC(struct p2p_msg_head_t *, pmsg, total_len); 60 | pmsg->magic = P2P_TRANSFER_MAGIC; 61 | pmsg->cmd_len = sizeof(struct p2p_msg_ping_t); 62 | pmsg->src_device_sn = s_ppt_client->device_sn; 63 | pmsg->cmd = P2P_TRANSFER_PING; 64 | 65 | pping = (struct p2p_msg_ping_t *)(pmsg->cmd_data); 66 | pping->device_sn = s_ppt_client->device_sn; 67 | pping->network_type = NP_PORT_RESTRICTED_CONE_NAT; 68 | 69 | if (-1 == bufferevent_write(s_ppt_client->pping_bev, pmsg, total_len)) 70 | { 71 | XL_DEBUG(EN_PRINT_ERROR, "call bufferevent_write() failed, send P2P_TRANSFER_PING failed"); 72 | goto ERR; 73 | } 74 | ERR: 75 | SAFE_FREE(pmsg); 76 | } 77 | 78 | static int connect_peer(struct p2p_msg_device_info_t *pdevice_info) 79 | { 80 | assert(pdevice_info != NULL); 81 | 82 | int sock = -1; 83 | struct sockaddr_in peer_addr; 84 | struct sockaddr_in local_addr; 85 | socklen_t addr_len = sizeof(peer_addr); 86 | int retry = 10; 87 | 88 | memset(&local_addr, 0, addr_len); 89 | local_addr.sin_family = AF_INET; 90 | local_addr.sin_addr.s_addr = s_ppt_client->local_ip; 91 | local_addr.sin_port = htons(P2P_TRANSFER_CLIENT_PORT); 92 | 93 | XL_DEBUG(EN_PRINT_DEBUG, "local_ip: %s", inet_ntoa(local_addr.sin_addr)); 94 | 95 | memset(&peer_addr, 0, addr_len); 96 | peer_addr.sin_family = AF_INET; 97 | peer_addr.sin_addr = pdevice_info->ip_addr; 98 | peer_addr.sin_port = pdevice_info->port; 99 | 100 | while (--retry) 101 | { 102 | sock = socket(AF_INET, SOCK_STREAM, 0); 103 | if (sock < 0) 104 | { 105 | XL_DEBUG(EN_PRINT_ERROR, "call socket() failed, err: %s", strerror(errno)); 106 | goto NEXT; 107 | } 108 | if (-1 == set_sock_opt(sock, SO_REUSEADDR|SO_REUSEPORT|SO_KEEPALIVE)) 109 | { 110 | XL_DEBUG(EN_PRINT_ERROR, "call set_sock_opt() failed"); 111 | goto NEXT; 112 | } 113 | if (-1 == bind(sock, (const struct sockaddr *)&local_addr, addr_len)) 114 | { 115 | XL_DEBUG(EN_PRINT_ERROR, "call bind() failed, err: %s", strerror(errno)); 116 | goto NEXT; 117 | } 118 | XL_DEBUG(EN_PRINT_DEBUG, "retry: %d, connect device_sn: %llu, ip: %s, port: %d", retry, pdevice_info->device_sn, 119 | inet_ntoa(peer_addr.sin_addr), htons(peer_addr.sin_port)); 120 | if (-1 == connect(sock, (const struct sockaddr *)&peer_addr, addr_len)) 121 | { 122 | XL_DEBUG(EN_PRINT_ERROR, "call connect() failed, ip_addr: %s, port: %d, errno: %d, err: %s", 123 | inet_ntoa(peer_addr.sin_addr), htons(peer_addr.sin_port), errno, strerror(errno)); 124 | if (errno != ETIMEDOUT) 125 | { 126 | sleep(20); 127 | } 128 | goto NEXT; 129 | } 130 | break; 131 | NEXT: 132 | SAFE_CLOSE(sock); 133 | } 134 | if (retry == 0) 135 | { 136 | XL_DEBUG(EN_PRINT_ERROR, "punch hole failed"); 137 | return -1; 138 | } 139 | else 140 | { 141 | XL_DEBUG(EN_PRINT_DEBUG, "punch hole success"); 142 | } 143 | return sock; 144 | } 145 | 146 | void *process_punch_hole_cmd_cb(UNUSED void *arg) 147 | { 148 | int sock = -1; 149 | 150 | struct p2p_msg_device_info_t *pdevice_info = (struct p2p_msg_device_info_t *)arg; 151 | 152 | sock = connect_peer(pdevice_info); 153 | if (-1 == sock) 154 | { 155 | XL_DEBUG(EN_PRINT_DEBUG, "call connect_peer() failed"); 156 | goto ERR; 157 | } 158 | char buf[10] = { '\0' }; 159 | if (-1 == recv(sock, buf, sizeof(buf), 0)) 160 | { 161 | XL_DEBUG(EN_PRINT_ERROR, "call recv() failed, err: %s", strerror(errno)); 162 | goto ERR; 163 | } 164 | XL_DEBUG(EN_PRINT_DEBUG, "recv buf: %s", buf); 165 | ERR: 166 | SAFE_CLOSE(sock); 167 | return NULL; 168 | } 169 | 170 | static int process_punch_hole_cmd(struct p2p_msg_device_info_t *pdevice_info) 171 | { 172 | assert(pdevice_info != NULL); 173 | 174 | pthread_t tid; 175 | if (0 != pthread_create(&tid, NULL, process_punch_hole_cmd_cb, pdevice_info)) 176 | { 177 | XL_DEBUG(EN_PRINT_ERROR, "call pthread_create() failed, err: %s", strerror(errno)); 178 | return -1; 179 | } 180 | return 0; 181 | } 182 | 183 | static void conn_read_cb(struct bufferevent *pbev, UNUSED void *user_data) 184 | { 185 | struct p2p_msg_head_t *prequest = NULL; 186 | struct p2p_msg_device_info_t *pdevice_info = NULL; 187 | int msg_head_len = sizeof(struct p2p_msg_head_t); 188 | int device_info_len = sizeof(struct p2p_msg_device_info_t); 189 | 190 | SAFE_CALLOC(struct p2p_msg_head_t *, prequest, msg_head_len); 191 | 192 | bufferevent_read(pbev, prequest, msg_head_len); 193 | XL_DEBUG(EN_PRINT_DEBUG, "cmd: %d", prequest->cmd); 194 | switch (prequest->cmd) 195 | { 196 | case P2P_TRANSFER_PUNCH_HOLE: 197 | SAFE_CALLOC(struct p2p_msg_device_info_t *, pdevice_info, device_info_len); 198 | bufferevent_read(pbev, pdevice_info, device_info_len); 199 | process_punch_hole_cmd(pdevice_info); 200 | break; 201 | default: 202 | break; 203 | } 204 | ERR: 205 | SAFE_FREE(prequest); 206 | } 207 | 208 | 209 | static void conn_event_cb(struct bufferevent *bev, short events, UNUSED void *user_data) 210 | { 211 | int conn_sock = bufferevent_getfd(bev); 212 | if (events & BEV_EVENT_EOF) 213 | { 214 | XL_DEBUG(EN_PRINT_DEBUG, "connection closed"); 215 | } 216 | else if (events & BEV_EVENT_ERROR) 217 | { 218 | XL_DEBUG(EN_PRINT_DEBUG, "got an error on the connection, err: %s", strerror(errno)); 219 | } 220 | bufferevent_free(bev); 221 | SAFE_CLOSE(conn_sock); 222 | } 223 | 224 | static int connect_server(struct p2p_transfer_client_t *ppt_client) 225 | { 226 | assert(ppt_client != NULL); 227 | 228 | int sock = -1; 229 | struct bufferevent *pping_bev = NULL; 230 | struct sockaddr_in server_addr; 231 | struct sockaddr_in local_addr; 232 | socklen_t addr_len = sizeof(server_addr); 233 | 234 | sock = socket(AF_INET, SOCK_STREAM, 0); 235 | if (-1 == sock) 236 | { 237 | XL_DEBUG(EN_PRINT_ERROR, "call socket() failed, err: %s", strerror(errno)); 238 | goto ERR; 239 | } 240 | if (-1 == set_sock_opt(sock, SO_REUSEADDR|SO_REUSEPORT|SO_KEEPALIVE)) 241 | { 242 | XL_DEBUG(EN_PRINT_ERROR, "call set_sock_opt() failed"); 243 | goto ERR; 244 | } 245 | memset(&local_addr, 0, addr_len); 246 | local_addr.sin_family = AF_INET; 247 | local_addr.sin_addr.s_addr = ppt_client->local_ip; 248 | local_addr.sin_port = htons(P2P_TRANSFER_CLIENT_PORT); 249 | 250 | if (-1 == bind(sock, (const struct sockaddr *)&local_addr, addr_len)) 251 | { 252 | XL_DEBUG(EN_PRINT_ERROR, "call bind() failed, err: %s", strerror(errno)); 253 | goto ERR; 254 | } 255 | 256 | memset(&server_addr, 0, addr_len); 257 | server_addr.sin_family = AF_INET; 258 | server_addr.sin_addr.s_addr = inet_addr(P2P_TRANSFER_SERVER_IP); 259 | server_addr.sin_port = htons(P2P_TRANSFER_SERVER_PORT); 260 | 261 | if (-1 == connect(sock, (const struct sockaddr *)&server_addr, addr_len)) 262 | { 263 | XL_DEBUG(EN_PRINT_ERROR, "call connect() failed, server ip: %s, err: %s", inet_ntoa(server_addr.sin_addr), 264 | strerror(errno)); 265 | goto ERR; 266 | } 267 | 268 | pping_bev = bufferevent_socket_new(ppt_client->base, sock, BEV_OPT_CLOSE_ON_FREE); 269 | if (NULL == pping_bev) 270 | { 271 | XL_DEBUG(EN_PRINT_ERROR, "call bufferevent_socket_new() failed, sock: %d", sock); 272 | goto ERR; 273 | } 274 | bufferevent_setcb(pping_bev, conn_read_cb, NULL, conn_event_cb, NULL); 275 | bufferevent_enable(pping_bev, EV_READ); 276 | 277 | ppt_client->conn_server_sock = sock; 278 | ppt_client->pping_bev = pping_bev; 279 | return 0; 280 | ERR: 281 | if (NULL != pping_bev) 282 | { 283 | bufferevent_free(pping_bev); 284 | } 285 | SAFE_CLOSE(sock); 286 | return -1; 287 | } 288 | 289 | static int listen_local(struct p2p_transfer_client_t *ppt_client) 290 | { 291 | assert(ppt_client != NULL); 292 | 293 | int sock = -1; 294 | struct evconnlistener *listener = NULL; 295 | struct sockaddr_in local_addr; 296 | socklen_t addr_len = sizeof(local_addr); 297 | 298 | memset(&local_addr, 0, addr_len); 299 | local_addr.sin_family = AF_INET; 300 | local_addr.sin_addr.s_addr = ppt_client->local_ip; 301 | local_addr.sin_port = htons(P2P_TRANSFER_CLIENT_PORT); 302 | 303 | listener = evconnlistener_new_bind(ppt_client->base, listener_cb, NULL, LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE, -1, 304 | (struct sockaddr*)&local_addr, addr_len); 305 | if (NULL == listener) 306 | { 307 | XL_DEBUG(EN_PRINT_ERROR, "call evconnlistener_new_bind() failed"); 308 | goto ERR; 309 | } 310 | sock = evconnlistener_get_fd(listener); 311 | if (-1 == set_sock_opt(sock, SO_REUSEADDR|SO_REUSEPORT|SO_KEEPALIVE)) 312 | { 313 | XL_DEBUG(EN_PRINT_ERROR, "call set_sock_opt() failed"); 314 | goto ERR; 315 | } 316 | ppt_client->listen_lcoal_sock = sock; 317 | ppt_client->listener = listener; 318 | return 0; 319 | ERR: 320 | if (listener != NULL) 321 | { 322 | evconnlistener_free(listener); 323 | } 324 | return -1; 325 | } 326 | 327 | static int add_ping_timer(struct p2p_transfer_client_t *ppt_client) 328 | { 329 | assert(ppt_client != NULL); 330 | 331 | struct event *ping_event = NULL; 332 | struct timeval ping_timeout = {5, 0}; 333 | 334 | ping_event = event_new(ppt_client->base, -1, EV_TIMEOUT, ping_cb, NULL); 335 | if (NULL == ping_event) 336 | { 337 | XL_DEBUG(EN_PRINT_ERROR, "call evtimer_new() failed"); 338 | goto ERR; 339 | } 340 | event_add(ping_event, &ping_timeout); 341 | event_active(ping_event, EV_TIMEOUT, 0); 342 | ppt_client->pping_event = ping_event; 343 | return 0; 344 | ERR: 345 | if (NULL != ping_event) 346 | { 347 | event_free(ping_event); 348 | } 349 | return -1; 350 | } 351 | void exit_cb(UNUSED evutil_socket_t sock, UNUSED short events, UNUSED void *user_data) 352 | { 353 | XL_DEBUG(EN_PRINT_NOTICE, "exit loop..."); 354 | event_loopbreak(); 355 | } 356 | 357 | struct p2p_transfer_client_t *init(int argc, char **argv) 358 | { 359 | struct p2p_transfer_client_t *ppt_client = NULL; 360 | 361 | if (-1 == configure_log(EN_PRINT_DEBUG, "/var/log/p2p_transfer_peer.log", 1)) 362 | { 363 | printf("call configure_log() failed"); 364 | return NULL; 365 | } 366 | 367 | ppt_client = (struct p2p_transfer_client_t *)calloc(1, sizeof(struct p2p_transfer_client_t)); 368 | if (NULL == ppt_client) 369 | { 370 | XL_DEBUG(EN_PRINT_ERROR, "call calloc() failed, err: %s", strerror(errno)); 371 | return NULL; 372 | } 373 | 374 | if (argc > 1) 375 | { 376 | ppt_client->device_sn = atoi(argv[1]); 377 | } 378 | else 379 | { 380 | ppt_client->device_sn = 1111; 381 | } 382 | if (argc > 2) 383 | { 384 | ppt_client->local_ip = inet_addr(argv[2]); 385 | } 386 | 387 | ppt_client->listen_lcoal_sock = ppt_client->conn_server_sock = -1; 388 | 389 | ppt_client->base = event_base_new(); 390 | if (NULL == ppt_client->base) 391 | { 392 | XL_DEBUG(EN_PRINT_ERROR, "call event_base_new() failed"); 393 | return NULL; 394 | } 395 | return ppt_client; 396 | } 397 | 398 | static void uninit(struct p2p_transfer_client_t *ppt_client) 399 | { 400 | if (ppt_client == NULL) 401 | { 402 | return ; 403 | } 404 | if (NULL != ppt_client->puser_event) 405 | { 406 | event_free(ppt_client->puser_event); 407 | ppt_client->puser_event = NULL; 408 | } 409 | if (NULL != ppt_client->pping_event) 410 | { 411 | event_free(ppt_client->pping_event); 412 | ppt_client->pping_event = NULL; 413 | } 414 | if (ppt_client->listener != NULL) 415 | { 416 | evconnlistener_free(ppt_client->listener); 417 | ppt_client->listener = NULL; 418 | } 419 | if (ppt_client->conn_server_sock > 0) 420 | { 421 | close(ppt_client->conn_server_sock); 422 | ppt_client->conn_server_sock = -1; 423 | } 424 | if (ppt_client->listen_lcoal_sock > 0) 425 | { 426 | close(ppt_client->listen_lcoal_sock); 427 | ppt_client->listen_lcoal_sock = -1; 428 | } 429 | if (ppt_client->base != NULL) 430 | { 431 | event_base_free(ppt_client->base); 432 | ppt_client->base = NULL; 433 | } 434 | destroy_log(); 435 | } 436 | 437 | static int punch_hole(struct p2p_msg_device_info_t *pdevice_info) 438 | { 439 | assert(pdevice_info != NULL); 440 | 441 | XL_DEBUG(EN_PRINT_ERROR, "be called"); 442 | 443 | int sock = -1; 444 | 445 | sock = connect_peer(pdevice_info); 446 | if (-1 == sock) 447 | { 448 | XL_DEBUG(EN_PRINT_DEBUG, "call connect_peer() failed"); 449 | goto ERR; 450 | } 451 | if (-1 == send(sock, "abc", strlen("abc"), 0)) 452 | { 453 | XL_DEBUG(EN_PRINT_ERROR, "call send() failed, err: %s", strerror(errno)); 454 | goto ERR; 455 | } 456 | XL_DEBUG(EN_PRINT_DEBUG, "p2p send success"); 457 | SAFE_CLOSE(sock); 458 | return 0; 459 | ERR: 460 | SAFE_CLOSE(sock); 461 | return -1; 462 | } 463 | 464 | void user_cb(UNUSED evutil_socket_t tmp_sock, UNUSED short events, UNUSED void *user_data) 465 | { 466 | XL_DEBUG(EN_PRINT_ERROR, "be called"); 467 | 468 | struct p2p_msg_head_t *prequest = NULL, *presponse = NULL; 469 | struct p2p_msg_device_info_t *pquery_device_info = NULL; 470 | int total_len = sizeof(struct p2p_msg_head_t) + sizeof(struct p2p_msg_device_info_t); 471 | int sock = s_ppt_client->conn_server_sock; 472 | uint64_t test_peer_device_sn = 2222; 473 | 474 | SAFE_CALLOC(struct p2p_msg_head_t *, prequest, total_len); 475 | SAFE_CALLOC(struct p2p_msg_head_t *, presponse, total_len); 476 | 477 | prequest->magic = P2P_TRANSFER_MAGIC; 478 | prequest->src_device_sn = s_ppt_client->device_sn; 479 | prequest->cmd_len = sizeof(struct p2p_msg_device_info_t); 480 | prequest->cmd = P2P_TRANSFER_QUERY_DEVICE_INFO_REQUEST; 481 | 482 | pquery_device_info = (struct p2p_msg_device_info_t *)(prequest->cmd_data); 483 | pquery_device_info->device_sn = test_peer_device_sn; 484 | 485 | if (-1 == send(sock, prequest, total_len, 0)) 486 | { 487 | XL_DEBUG(EN_PRINT_ERROR, "call send() failed, total_len: %d, err: %s", total_len, strerror(errno)); 488 | goto ERR; 489 | } 490 | 491 | XL_DEBUG(EN_PRINT_DEBUG, "recv..."); 492 | if (-1 == recv(sock, presponse, total_len, 0)) 493 | { 494 | XL_DEBUG(EN_PRINT_ERROR, "call recv() failed, total_len: %d, err: %s", total_len, strerror(errno)); 495 | goto ERR; 496 | } 497 | if (presponse->cmd == P2P_TRANSFER_UNKNOWN_CMD) 498 | { 499 | XL_DEBUG(EN_PRINT_ERROR, "query device info failed, device_sn: %llu", pquery_device_info->device_sn); 500 | goto ERR; 501 | } 502 | 503 | pquery_device_info = (struct p2p_msg_device_info_t *)(presponse->cmd_data); 504 | XL_DEBUG(EN_PRINT_DEBUG, "peer: %llu, ip: %s, port: %d", test_peer_device_sn, inet_ntoa(pquery_device_info->ip_addr), htons(pquery_device_info->port)); 505 | 506 | (void)punch_hole(pquery_device_info); 507 | ERR: 508 | SAFE_FREE(prequest); 509 | SAFE_FREE(presponse); 510 | } 511 | 512 | static int add_user_timer(struct p2p_transfer_client_t *ppt_client) 513 | { 514 | struct event *puser_event = NULL; 515 | struct timeval user_timeout = { 10, 0 }; 516 | 517 | puser_event = event_new(ppt_client->base, -1, EV_TIMEOUT, user_cb, NULL); 518 | if (NULL == puser_event) 519 | { 520 | XL_DEBUG(EN_PRINT_ERROR, "call event_new() failed"); 521 | goto ERR; 522 | } 523 | event_add(puser_event, &user_timeout); 524 | ppt_client->puser_event = puser_event; 525 | return 0; 526 | ERR: 527 | if (NULL != puser_event) 528 | { 529 | event_free(puser_event); 530 | } 531 | return -1; 532 | } 533 | 534 | int main(int argc, char **argv) 535 | { 536 | s_ppt_client = init(argc, argv); 537 | if (NULL == s_ppt_client) 538 | { 539 | XL_DEBUG(EN_PRINT_ERROR, "call init() failed"); 540 | goto ERR; 541 | } 542 | 543 | if (-1 == listen_local(s_ppt_client)) 544 | { 545 | XL_DEBUG(EN_PRINT_ERROR, "call listen_local() failed"); 546 | goto ERR; 547 | } 548 | if (-1 == connect_server(s_ppt_client)) 549 | { 550 | XL_DEBUG(EN_PRINT_ERROR, "call connect_server() failed"); 551 | goto ERR; 552 | } 553 | if (-1 == add_ping_timer(s_ppt_client)) 554 | { 555 | XL_DEBUG(EN_PRINT_ERROR, "call add_ping_timer() failed"); 556 | goto ERR; 557 | } 558 | 559 | 560 | XL_DEBUG(EN_PRINT_NOTICE, "device_sn: %llu, listen_local_sock: %d, conn_server_sock: %d", 561 | s_ppt_client->device_sn, s_ppt_client->listen_lcoal_sock, s_ppt_client->conn_server_sock); 562 | 563 | if (s_ppt_client->device_sn != 2222) 564 | { 565 | if (-1 == add_user_timer(s_ppt_client)) 566 | { 567 | XL_DEBUG(EN_PRINT_ERROR, "call add_user_timer() failed"); 568 | goto ERR; 569 | } 570 | } 571 | 572 | XL_DEBUG(EN_PRINT_NOTICE, "enter event_base_dispatch()..."); 573 | if (-1 == event_base_dispatch(s_ppt_client->base)) 574 | { 575 | XL_DEBUG(EN_PRINT_ERROR, "call event_base_dispatch() failed"); 576 | goto ERR; 577 | } 578 | XL_DEBUG(EN_PRINT_NOTICE, "exit"); 579 | uninit(s_ppt_client); 580 | return 0; 581 | ERR: 582 | uninit(s_ppt_client); 583 | return -1; 584 | } -------------------------------------------------------------------------------- /p2p_transfer_tcp/p2p_transfer_server/Makefile: -------------------------------------------------------------------------------- 1 | all:p2p_transfer_server 2 | 3 | p2p_transfer_server:clean 4 | gcc -o p2p_transfer_server -g -O0 -W -Wall -Werror p2p_transfer_server.c p2p_transfer.c log.c -levent -lm 5 | clean : 6 | -rm -f p2p_transfer_server 7 | -------------------------------------------------------------------------------- /p2p_transfer_tcp/p2p_transfer_server/list.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2011 Felix Fietkau 3 | * Copyright (c) 2010 Isilon Systems, Inc. 4 | * Copyright (c) 2010 iX Systems, Inc. 5 | * Copyright (c) 2010 Panasas, Inc. 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions 10 | * are met: 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice unmodified, this list of conditions, and the following 13 | * disclaimer. 14 | * 2. Redistributions in binary form must reproduce the above copyright 15 | * notice, this list of conditions and the following disclaimer in the 16 | * documentation and/or other materials provided with the distribution. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | #ifndef _LINUX_LIST_H_ 30 | #define _LINUX_LIST_H_ 31 | 32 | #include 33 | #include 34 | 35 | #define prefetch(x) 36 | 37 | #ifndef container_of 38 | #define container_of(ptr, type, member) \ 39 | ({ \ 40 | const typeof(((type *) NULL)->member) *__mptr = (ptr); \ 41 | (type *) ((char *) __mptr - offsetof(type, member)); \ 42 | }) 43 | #endif 44 | 45 | struct list_head 46 | { 47 | struct list_head *next; 48 | struct list_head *prev; 49 | }; 50 | 51 | #define LIST_HEAD_INIT(name) { &(name), &(name) } 52 | #undef LIST_HEAD 53 | #define LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name) 54 | 55 | static inline void 56 | INIT_LIST_HEAD(struct list_head *list) 57 | { 58 | list->next = list->prev = list; 59 | } 60 | 61 | static inline bool 62 | list_empty(const struct list_head *head) 63 | { 64 | return (head->next == head); 65 | } 66 | 67 | static inline bool 68 | list_is_first(const struct list_head *list, 69 | const struct list_head *head) 70 | { 71 | return list->prev == head; 72 | } 73 | 74 | static inline bool 75 | list_is_last(const struct list_head *list, 76 | const struct list_head *head) 77 | { 78 | return list->next == head; 79 | } 80 | 81 | static inline void 82 | _list_del(struct list_head *entry) 83 | { 84 | entry->next->prev = entry->prev; 85 | entry->prev->next = entry->next; 86 | } 87 | 88 | static inline void 89 | list_del(struct list_head *entry) 90 | { 91 | _list_del(entry); 92 | entry->next = entry->prev = NULL; 93 | } 94 | 95 | static inline void 96 | _list_add(struct list_head *_new, struct list_head *prev, 97 | struct list_head *next) 98 | { 99 | 100 | next->prev = _new; 101 | _new->next = next; 102 | _new->prev = prev; 103 | prev->next = _new; 104 | } 105 | 106 | static inline void 107 | list_del_init(struct list_head *entry) 108 | { 109 | _list_del(entry); 110 | INIT_LIST_HEAD(entry); 111 | } 112 | 113 | #define list_entry(ptr, type, field) container_of(ptr, type, field) 114 | #define list_first_entry(ptr, type, field) list_entry((ptr)->next, type, field) 115 | #define list_last_entry(ptr, type, field) list_entry((ptr)->prev, type, field) 116 | 117 | #define list_for_each(p, head) \ 118 | for (p = (head)->next; p != (head); p = p->next) 119 | 120 | #define list_for_each_safe(p, n, head) \ 121 | for (p = (head)->next, n = p->next; p != (head); p = n, n = p->next) 122 | 123 | #define list_for_each_entry(p, h, field) \ 124 | for (p = list_first_entry(h, typeof(*p), field); &p->field != (h); \ 125 | p = list_entry(p->field.next, typeof(*p), field)) 126 | 127 | #define list_for_each_entry_safe(p, n, h, field) \ 128 | for (p = list_first_entry(h, typeof(*p), field), \ 129 | n = list_entry(p->field.next, typeof(*p), field); &p->field != (h);\ 130 | p = n, n = list_entry(n->field.next, typeof(*n), field)) 131 | 132 | #define list_for_each_entry_reverse(p, h, field) \ 133 | for (p = list_last_entry(h, typeof(*p), field); &p->field != (h); \ 134 | p = list_entry(p->field.prev, typeof(*p), field)) 135 | 136 | #define list_for_each_prev(p, h) for (p = (h)->prev; p != (h); p = p->prev) 137 | #define list_for_each_prev_safe(p, n, h) for (p = (h)->prev, n = p->prev; p != (h); p = n, n = p->prev) 138 | 139 | static inline void 140 | list_add(struct list_head *_new, struct list_head *head) 141 | { 142 | _list_add(_new, head, head->next); 143 | } 144 | 145 | static inline void 146 | list_add_tail(struct list_head *_new, struct list_head *head) 147 | { 148 | _list_add(_new, head->prev, head); 149 | } 150 | 151 | static inline void 152 | list_move(struct list_head *list, struct list_head *head) 153 | { 154 | _list_del(list); 155 | list_add(list, head); 156 | } 157 | 158 | static inline void 159 | list_move_tail(struct list_head *entry, struct list_head *head) 160 | { 161 | _list_del(entry); 162 | list_add_tail(entry, head); 163 | } 164 | 165 | static inline void 166 | _list_splice(const struct list_head *list, struct list_head *prev, 167 | struct list_head *next) 168 | { 169 | struct list_head *first; 170 | struct list_head *last; 171 | 172 | if (list_empty(list)) 173 | return; 174 | 175 | first = list->next; 176 | last = list->prev; 177 | first->prev = prev; 178 | prev->next = first; 179 | last->next = next; 180 | next->prev = last; 181 | } 182 | 183 | static inline void 184 | list_splice(const struct list_head *list, struct list_head *head) 185 | { 186 | _list_splice(list, head, head->next); 187 | } 188 | 189 | static inline void 190 | list_splice_tail(struct list_head *list, struct list_head *head) 191 | { 192 | _list_splice(list, head->prev, head); 193 | } 194 | 195 | static inline void 196 | list_splice_init(struct list_head *list, struct list_head *head) 197 | { 198 | _list_splice(list, head, head->next); 199 | INIT_LIST_HEAD(list); 200 | } 201 | 202 | static inline void 203 | list_splice_tail_init(struct list_head *list, struct list_head *head) 204 | { 205 | _list_splice(list, head->prev, head); 206 | INIT_LIST_HEAD(list); 207 | } 208 | 209 | #endif /* _LINUX_LIST_H_ */ 210 | -------------------------------------------------------------------------------- /p2p_transfer_tcp/p2p_transfer_server/log.c: -------------------------------------------------------------------------------- 1 | #include "log.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | static const char* LEVEL_NAMES[] = {"DEBUG", "INFO", "NOTICE", "WARN", "ERROR", "FATAL"}; 10 | 11 | static int enable_console = 1; 12 | static FILE *log_stream = NULL; 13 | static int log_level = EN_PRINT_INFO; 14 | 15 | int configure_log(int lvl, const char* file, int use_console) { 16 | FILE *stream = NULL; 17 | int res = 0; 18 | 19 | if (lvl > EN_PRINT_ERROR) 20 | lvl = EN_PRINT_ERROR; 21 | else if (lvl < EN_PRINT_DEBUG) 22 | lvl = EN_PRINT_DEBUG; 23 | log_level = lvl; 24 | enable_console = use_console; 25 | if (file != NULL) { 26 | stream = fopen(file, "a"); 27 | if (stream == NULL) { 28 | XL_DEBUG(EN_PRINT_ERROR, "error opening log file, err: %s", strerror(errno)); 29 | res = 1; 30 | } else { 31 | log_stream = stream; 32 | } 33 | } 34 | 35 | return res; 36 | } 37 | 38 | void destroy_log() 39 | { 40 | if (log_stream != NULL) 41 | { 42 | fclose(log_stream); 43 | } 44 | } 45 | 46 | void logging(int lvl, const char *file, const char *func, const int line, const char *fmt, ...) { 47 | va_list ap; 48 | char buffer[512], *ptr = buffer; 49 | int size, cap = 512; 50 | time_t ts; 51 | struct tm *tmp; 52 | 53 | if (lvl < log_level) { 54 | return; 55 | } 56 | 57 | ts = time(NULL); 58 | tmp = localtime(&ts); 59 | size = strftime(ptr, cap, "[%Y-%m-%d %H:%M:%S]", tmp); 60 | ptr += size; 61 | cap -= size; 62 | size = snprintf(ptr, cap, "[%6s][%s:%d][%s] ", 63 | LEVEL_NAMES[lvl], file, line, func); 64 | ptr += size; 65 | cap -= size; 66 | 67 | va_start(ap, fmt); 68 | size = vsnprintf(ptr, cap, fmt, ap); 69 | va_end(ap); 70 | 71 | *(ptr + size) = '\n'; 72 | *(ptr + size + 1) = '\0'; 73 | 74 | if (enable_console) { 75 | if (lvl >= EN_PRINT_WARN) { 76 | fputs(buffer, stderr); 77 | } else { 78 | fputs(buffer, stdout); 79 | } 80 | } 81 | 82 | if (log_stream != NULL) { 83 | fputs(buffer, log_stream); 84 | fflush(log_stream); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /p2p_transfer_tcp/p2p_transfer_server/log.h: -------------------------------------------------------------------------------- 1 | #ifndef __LOG_H_ 2 | #define __LOG_H_ 3 | 4 | enum _log_level { 5 | EN_PRINT_DEBUG, 6 | EN_PRINT_INFO, 7 | EN_PRINT_NOTICE, 8 | EN_PRINT_WARN, 9 | EN_PRINT_ERROR, 10 | EN_PRINT_FATAL, 11 | }; 12 | 13 | int configure_log(int level, const char* file, int use_console); 14 | void destroy_log(); 15 | 16 | void logging(int lvl, const char *file, const char *func, const int line, const char *fmt, ...); 17 | 18 | #define XL_DEBUG(lvl, fmt, ...) logging(lvl, __FILE__, __FUNCTION__, __LINE__, fmt, ##__VA_ARGS__) 19 | 20 | #endif /* __LOG_H_ */ 21 | -------------------------------------------------------------------------------- /p2p_transfer_tcp/p2p_transfer_server/p2p_transfer.c: -------------------------------------------------------------------------------- 1 | #include "p2p_transfer.h" 2 | #include "log.h" 3 | #include 4 | #include 5 | 6 | const char *get_string_network_type(int network_type) 7 | { 8 | static char *s_network_type[] = { 9 | "UNKNOWN", 10 | "PUBLIC_NETWORK", 11 | "FULL_CONE_NAT", 12 | "RESTRICTED_CONE_NAT", 13 | "PORT_RESTRICTED_CONE_NAT", 14 | "SYMMETRIC_NAT", 15 | }; 16 | if (network_type < NP_UNKNOWN || network_type > NP_SYMMETRIC_NAT) 17 | { 18 | network_type = NP_UNKNOWN; 19 | } 20 | return s_network_type[network_type]; 21 | } 22 | 23 | int set_sock_opt(int sock, int flag) 24 | { 25 | int enable = 1; 26 | 27 | if (flag & SO_REUSEADDR) 28 | { 29 | if (-1 == setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable))) 30 | { 31 | XL_DEBUG(EN_PRINT_ERROR, "call setsockopt() failed, set SO_REUSEPORT failed, err: %s", strerror(errno)); 32 | return -1; 33 | } 34 | else 35 | { 36 | XL_DEBUG(EN_PRINT_ERROR, "set SO_REUSEPORT success"); 37 | } 38 | } 39 | if (flag & SO_REUSEPORT) 40 | { 41 | if (-1 == setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(enable))) 42 | { 43 | XL_DEBUG(EN_PRINT_ERROR, "call setsockopt() failed, set SO_REUSEPORT failed, err: %s", strerror(errno)); 44 | return -1; 45 | } 46 | } 47 | if (flag & SO_KEEPALIVE) 48 | { 49 | if (-1 == setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable))) 50 | { 51 | XL_DEBUG(EN_PRINT_ERROR, "call setsockopt() failed, set SO_KEEPALIVE failed, err: %s", strerror(errno)); 52 | return -1; 53 | } 54 | } 55 | return 0; 56 | } -------------------------------------------------------------------------------- /p2p_transfer_tcp/p2p_transfer_server/p2p_transfer.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zhangli88/p2p_punch_hole/32fc7f58d921cdebad588e797c6159f890228ad1/p2p_transfer_tcp/p2p_transfer_server/p2p_transfer.h -------------------------------------------------------------------------------- /p2p_transfer_tcp/p2p_transfer_server/p2p_transfer_server: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zhangli88/p2p_punch_hole/32fc7f58d921cdebad588e797c6159f890228ad1/p2p_transfer_tcp/p2p_transfer_server/p2p_transfer_server -------------------------------------------------------------------------------- /p2p_transfer_tcp/p2p_transfer_server/p2p_transfer_server.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zhangli88/p2p_punch_hole/32fc7f58d921cdebad588e797c6159f890228ad1/p2p_transfer_tcp/p2p_transfer_server/p2p_transfer_server.c -------------------------------------------------------------------------------- /p2p_transfer_udp/p2p_transfer_peer/Makefile: -------------------------------------------------------------------------------- 1 | all:p2p_transfer_udp_peer 2 | 3 | p2p_transfer_udp_peer:clean 4 | gcc -o p2p_transfer_udp_peer -g3 -gdwarf-2 -g -O0 -W -Wall -Werror p2p_transfer_peer.c p2p_transfer.c log.c -levent -lm -lpthread 5 | clean : 6 | -rm -f p2p_transfer_udp_peer 7 | -------------------------------------------------------------------------------- /p2p_transfer_udp/p2p_transfer_peer/log.c: -------------------------------------------------------------------------------- 1 | #include "log.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | static const char* LEVEL_NAMES[] = {"DEBUG", "INFO", "NOTICE", "WARN", "ERROR", "FATAL"}; 10 | 11 | static int enable_console = 1; 12 | static FILE *log_stream = NULL; 13 | static int log_level = EN_PRINT_INFO; 14 | 15 | int configure_log(int lvl, const char* file, int use_console) { 16 | FILE *stream = NULL; 17 | int res = 0; 18 | 19 | if (lvl > EN_PRINT_ERROR) 20 | lvl = EN_PRINT_ERROR; 21 | else if (lvl < EN_PRINT_DEBUG) 22 | lvl = EN_PRINT_DEBUG; 23 | log_level = lvl; 24 | enable_console = use_console; 25 | if (file != NULL) { 26 | stream = fopen(file, "a"); 27 | if (stream == NULL) { 28 | XL_DEBUG(EN_PRINT_ERROR, "error opening log file, err: %s", strerror(errno)); 29 | res = 1; 30 | } else { 31 | log_stream = stream; 32 | } 33 | } 34 | 35 | return res; 36 | } 37 | 38 | void destroy_log() 39 | { 40 | if (log_stream != NULL) 41 | { 42 | fclose(log_stream); 43 | } 44 | } 45 | 46 | void logging(int lvl, const char *file, const char *func, const int line, const char *fmt, ...) { 47 | va_list ap; 48 | char buffer[512], *ptr = buffer; 49 | int size, cap = 512; 50 | time_t ts; 51 | struct tm *tmp; 52 | 53 | if (lvl < log_level) { 54 | return; 55 | } 56 | 57 | ts = time(NULL); 58 | tmp = localtime(&ts); 59 | size = strftime(ptr, cap, "[%Y-%m-%d %H:%M:%S]", tmp); 60 | ptr += size; 61 | cap -= size; 62 | size = snprintf(ptr, cap, "[%6s][%s:%d][%s] ", 63 | LEVEL_NAMES[lvl], file, line, func); 64 | ptr += size; 65 | cap -= size; 66 | 67 | va_start(ap, fmt); 68 | size = vsnprintf(ptr, cap, fmt, ap); 69 | va_end(ap); 70 | 71 | *(ptr + size) = '\n'; 72 | *(ptr + size + 1) = '\0'; 73 | 74 | if (enable_console) { 75 | if (lvl >= EN_PRINT_WARN) { 76 | fputs(buffer, stderr); 77 | } else { 78 | fputs(buffer, stdout); 79 | } 80 | } 81 | 82 | if (log_stream != NULL) { 83 | fputs(buffer, log_stream); 84 | fflush(log_stream); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /p2p_transfer_udp/p2p_transfer_peer/log.h: -------------------------------------------------------------------------------- 1 | #ifndef __LOG_H_ 2 | #define __LOG_H_ 3 | 4 | enum _log_level { 5 | EN_PRINT_DEBUG, 6 | EN_PRINT_INFO, 7 | EN_PRINT_NOTICE, 8 | EN_PRINT_WARN, 9 | EN_PRINT_ERROR, 10 | EN_PRINT_FATAL, 11 | }; 12 | 13 | int configure_log(int level, const char* file, int use_console); 14 | void destroy_log(); 15 | 16 | void logging(int lvl, const char *file, const char *func, const int line, const char *fmt, ...); 17 | 18 | #define XL_DEBUG(lvl, fmt, ...) logging(lvl, __FILE__, __FUNCTION__, __LINE__, fmt, ##__VA_ARGS__) 19 | 20 | #endif /* __LOG_H_ */ 21 | -------------------------------------------------------------------------------- /p2p_transfer_udp/p2p_transfer_peer/p2p_transfer.c: -------------------------------------------------------------------------------- 1 | #include "p2p_transfer.h" 2 | #include "log.h" 3 | #include 4 | #include 5 | #include 6 | 7 | const char *get_string_network_type(int network_type) 8 | { 9 | static char *s_network_type[] = { 10 | "UNKNOWN", 11 | "PUBLIC_NETWORK", 12 | "FULL_CONE_NAT", 13 | "RESTRICTED_CONE_NAT", 14 | "PORT_RESTRICTED_CONE_NAT", 15 | "SYMMETRIC_NAT", 16 | }; 17 | if (network_type < NP_UNKNOWN || network_type > NP_SYMMETRIC_NAT) 18 | { 19 | network_type = NP_UNKNOWN; 20 | } 21 | return s_network_type[network_type]; 22 | } 23 | 24 | int set_sock_opt(int sock, int flag) 25 | { 26 | int enable = 1; 27 | 28 | if (flag & SO_REUSEADDR) 29 | { 30 | if (-1 == setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable))) 31 | { 32 | XL_DEBUG(EN_PRINT_ERROR, "call setsockopt() failed, set SO_REUSEPORT failed, err: %s", strerror(errno)); 33 | return -1; 34 | } 35 | else 36 | { 37 | XL_DEBUG(EN_PRINT_ERROR, "set SO_REUSEPORT success"); 38 | } 39 | } 40 | #ifndef NO_SUPPORT_REUSEPORT 41 | if (flag & SO_REUSEPORT) 42 | { 43 | if (-1 == setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(enable))) 44 | { 45 | XL_DEBUG(EN_PRINT_ERROR, "call setsockopt() failed, set SO_REUSEPORT failed, err: %s", strerror(errno)); 46 | return -1; 47 | } 48 | } 49 | #endif 50 | if (flag & SO_KEEPALIVE) 51 | { 52 | if (-1 == setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable))) 53 | { 54 | XL_DEBUG(EN_PRINT_ERROR, "call setsockopt() failed, set SO_KEEPALIVE failed, err: %s", strerror(errno)); 55 | return -1; 56 | } 57 | } 58 | return 0; 59 | } 60 | 61 | void generate_server_addr(struct sockaddr_in *paddr) 62 | { 63 | assert(paddr != NULL); 64 | 65 | memset(paddr, 0, sizeof(*paddr)); 66 | paddr->sin_family = AF_INET; 67 | paddr->sin_addr.s_addr = inet_addr(P2P_TRANSFER_SERVER_IP); 68 | paddr->sin_port = htons(P2P_TRANSFER_SERVER_PORT); 69 | } 70 | 71 | void generate_peer_addr(struct sockaddr_in *paddr, const struct p2p_msg_device_info_t *pdevice_info) 72 | { 73 | assert(paddr != NULL); 74 | assert(pdevice_info != NULL); 75 | 76 | memset(paddr, 0, sizeof(*paddr)); 77 | paddr->sin_family = AF_INET; 78 | paddr->sin_addr = pdevice_info->ip_addr; 79 | paddr->sin_port = pdevice_info->port; 80 | XL_DEBUG(EN_PRINT_DEBUG, "ip: %s, port: %d", inet_ntoa(paddr->sin_addr), ntohs(paddr->sin_port)); 81 | } 82 | 83 | const char *get_string_cmd(int cmd) 84 | { 85 | static char *s_cmd[] = { 86 | "P2P_TRANSFER_UNKNOWN_CMD", 87 | "P2P_TRANSFER_PING", 88 | "P2P_TRANSFER_QUERY_DEVICE_INFO_REQUEST", 89 | "P2P_TRANSFER_QUERY_DEVICE_INFO_RESPONSE", 90 | "P2P_TRANSFER_PUNCH_HOLE", 91 | "P2P_TRANSFER_PUNCH_HOLE_TO_PEER", 92 | "P2P_TRANSFER_USER_DATA", 93 | }; 94 | if (cmd < P2P_TRANSFER_UNKNOWN_CMD || cmd > P2P_TRANSFER_USER_DATA) 95 | { 96 | cmd = P2P_TRANSFER_UNKNOWN_CMD; 97 | } 98 | return s_cmd[cmd]; 99 | } -------------------------------------------------------------------------------- /p2p_transfer_udp/p2p_transfer_peer/p2p_transfer.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zhangli88/p2p_punch_hole/32fc7f58d921cdebad588e797c6159f890228ad1/p2p_transfer_udp/p2p_transfer_peer/p2p_transfer.h -------------------------------------------------------------------------------- /p2p_transfer_udp/p2p_transfer_peer/p2p_transfer_peer.c: -------------------------------------------------------------------------------- 1 | //#include "xl_common.h" 2 | #include "log.h" 3 | #include "p2p_transfer.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | 24 | #define P2P_TRANSFER_CLIENT_PORT (5152) 25 | static int s_my_device_sn; 26 | static int s_sock = -1; 27 | 28 | int process_punch_hole_cmd(struct p2p_msg_device_info_t *pdevice_info) 29 | { 30 | struct sockaddr_in peer_addr; 31 | struct p2p_msg_head_t *pmsg = NULL; 32 | int total_len = sizeof(struct p2p_msg_head_t); 33 | 34 | SAFE_CALLOC(struct p2p_msg_head_t *, pmsg, total_len); 35 | pmsg->magic = P2P_TRANSFER_MAGIC; 36 | pmsg->cmd_len = 0; 37 | pmsg->src_device_sn = s_my_device_sn; 38 | pmsg->cmd = P2P_TRANSFER_PUNCH_HOLE_TO_PEER; 39 | 40 | generate_peer_addr(&peer_addr, pdevice_info); 41 | SAFE_SENDTO(s_sock, pmsg, total_len, &peer_addr); 42 | XL_DEBUG(EN_PRINT_DEBUG, "send P2P_TRANSFER_PUNCH_HOLE_TO_PEER success"); 43 | SAFE_FREE(pmsg); 44 | return 0; 45 | ERR: 46 | XL_DEBUG(EN_PRINT_DEBUG, "send P2P_TRANSFER_PUNCH_HOLE_TO_PEER failed"); 47 | SAFE_FREE(pmsg); 48 | return -1; 49 | } 50 | 51 | int punch_hole(const struct p2p_msg_device_info_t *pdevice_info) 52 | { 53 | assert(pdevice_info != NULL); 54 | 55 | XL_DEBUG(EN_PRINT_DEBUG, "be called"); 56 | 57 | sleep(5); 58 | 59 | struct sockaddr_in peer_addr; 60 | struct p2p_msg_head_t *pmsg = NULL; 61 | char *user_data = "abc"; 62 | int data_len = strlen(user_data) + 1; 63 | int total_len = sizeof(*pmsg) + data_len; 64 | 65 | SAFE_CALLOC(struct p2p_msg_head_t *, pmsg, total_len); 66 | 67 | pmsg->magic = P2P_TRANSFER_MAGIC; 68 | pmsg->src_device_sn = s_my_device_sn; 69 | pmsg->cmd = P2P_TRANSFER_USER_DATA; 70 | pmsg->cmd_len = data_len; 71 | memcpy(pmsg->cmd_data, user_data, data_len); 72 | 73 | generate_peer_addr(&peer_addr, pdevice_info); 74 | SAFE_SENDTO(s_sock, pmsg, total_len, &peer_addr); 75 | 76 | XL_DEBUG(EN_PRINT_DEBUG, "send P2P_TRANSFER_USER_DATA success"); 77 | SAFE_FREE(pmsg); 78 | return 0; 79 | ERR: 80 | XL_DEBUG(EN_PRINT_DEBUG, "send P2P_TRANSFER_USER_DATA failed"); 81 | SAFE_FREE(pmsg); 82 | return -1; 83 | } 84 | 85 | void read_cb(UNUSED evutil_socket_t sock, UNUSED short events, UNUSED void *user_data) 86 | { 87 | struct p2p_msg_head_t *prequest = NULL; 88 | struct p2p_msg_device_info_t *pdevice_info = NULL; 89 | 90 | SAFE_CALLOC(struct p2p_msg_head_t *, prequest, P2P_TRANSFER_MAX_MSG_LENGTH); 91 | 92 | SAFE_RECVFROM(s_sock, prequest, P2P_TRANSFER_MAX_MSG_LENGTH, NULL); 93 | XL_DEBUG(EN_PRINT_DEBUG, "cmd: %s", get_string_cmd(prequest->cmd)); 94 | switch (prequest->cmd) 95 | { 96 | case P2P_TRANSFER_PUNCH_HOLE: 97 | pdevice_info = (struct p2p_msg_device_info_t *)(prequest->cmd_data); 98 | (void)process_punch_hole_cmd(pdevice_info); 99 | break; 100 | case P2P_TRANSFER_QUERY_DEVICE_INFO_RESPONSE: 101 | pdevice_info = (struct p2p_msg_device_info_t *)(prequest->cmd_data); 102 | (void)punch_hole(pdevice_info); 103 | case P2P_TRANSFER_PUNCH_HOLE_TO_PEER: 104 | // nothing 105 | break; 106 | case P2P_TRANSFER_USER_DATA: 107 | XL_DEBUG(EN_PRINT_DEBUG, "punch hole success, user_data: %s", (char*)(prequest->cmd_data)); 108 | default: 109 | break; 110 | } 111 | ERR: 112 | SAFE_FREE(prequest); 113 | } 114 | 115 | void ping_cb(UNUSED evutil_socket_t sock, UNUSED short events, UNUSED void *user_data) 116 | { 117 | XL_DEBUG(EN_PRINT_DEBUG, "ping..."); 118 | 119 | struct p2p_msg_head_t *pmsg = NULL; 120 | struct p2p_msg_ping_t *pping = NULL; 121 | int total_len = sizeof(struct p2p_msg_head_t) + sizeof(struct p2p_msg_ping_t); 122 | struct sockaddr_in server_addr; 123 | 124 | SAFE_CALLOC(struct p2p_msg_head_t *, pmsg, total_len); 125 | pmsg->magic = P2P_TRANSFER_MAGIC; 126 | pmsg->cmd_len = sizeof(struct p2p_msg_ping_t); 127 | pmsg->src_device_sn = s_my_device_sn; 128 | pmsg->cmd = P2P_TRANSFER_PING; 129 | 130 | pping = (struct p2p_msg_ping_t *)(pmsg->cmd_data); 131 | pping->device_sn = s_my_device_sn; 132 | pping->network_type = NP_PORT_RESTRICTED_CONE_NAT; 133 | 134 | generate_server_addr(&server_addr); 135 | SAFE_SENDTO(s_sock, pmsg, total_len, &server_addr); 136 | ERR: 137 | SAFE_FREE(pmsg); 138 | } 139 | 140 | void user_cb(UNUSED evutil_socket_t sock, UNUSED short events, UNUSED void *user_data) 141 | { 142 | struct p2p_msg_head_t *prequest = NULL, *presponse = NULL; 143 | struct p2p_msg_device_info_t *pquery_device_info = NULL; 144 | int total_len = sizeof(struct p2p_msg_head_t) + sizeof(struct p2p_msg_device_info_t); 145 | struct sockaddr_in server_addr; 146 | 147 | SAFE_CALLOC(struct p2p_msg_head_t *, prequest, total_len); 148 | SAFE_CALLOC(struct p2p_msg_head_t *, presponse, total_len); 149 | 150 | prequest->magic = P2P_TRANSFER_MAGIC; 151 | prequest->src_device_sn = s_my_device_sn; 152 | prequest->cmd_len = sizeof(struct p2p_msg_device_info_t); 153 | prequest->cmd = P2P_TRANSFER_QUERY_DEVICE_INFO_REQUEST; 154 | 155 | pquery_device_info = (struct p2p_msg_device_info_t *)(prequest->cmd_data); 156 | pquery_device_info->device_sn = 2222; 157 | 158 | generate_server_addr(&server_addr); 159 | SAFE_SENDTO(s_sock, prequest, total_len, &server_addr); 160 | ERR: 161 | SAFE_FREE(prequest); 162 | SAFE_FREE(presponse); 163 | } 164 | 165 | int main(int argc, char **argv) 166 | { 167 | 168 | struct event_base *pbase = NULL; 169 | int sock = -1; 170 | struct event *pread_event = NULL; 171 | struct event *pping_event = NULL; 172 | struct timeval ping_timeout = {5, 0}; 173 | struct event *puser_event = NULL; 174 | struct timeval user_timeout = {10, 0}; 175 | 176 | struct sockaddr_in local_addr; 177 | socklen_t addr_len = sizeof(local_addr); 178 | 179 | if (-1 == configure_log(EN_PRINT_DEBUG, "/var/log/p2p_transfer_peer.log", 1)) 180 | { 181 | printf("call configure_log() failed"); 182 | goto ERR; 183 | } 184 | 185 | if (argc < 2) 186 | { 187 | printf("./p2p_transfer_peer my_device_sn\n"); 188 | goto ERR; 189 | } 190 | s_my_device_sn = atoi(argv[1]); 191 | XL_DEBUG(EN_PRINT_DEBUG, "my_device_sn: %d", s_my_device_sn); 192 | 193 | memset(&local_addr, 0, addr_len); 194 | local_addr.sin_family = AF_INET; 195 | local_addr.sin_addr.s_addr = htonl(INADDR_ANY); 196 | local_addr.sin_port = htons(P2P_TRANSFER_CLIENT_PORT); 197 | 198 | sock = socket(AF_INET, SOCK_DGRAM, 0); 199 | if (sock == -1) 200 | { 201 | XL_DEBUG(EN_PRINT_ERROR, "call socket() failed, err: %s", strerror(errno)); 202 | goto ERR; 203 | } 204 | if (-1 == bind(sock, (const struct sockaddr *)&local_addr, addr_len)) 205 | { 206 | XL_DEBUG(EN_PRINT_ERROR, "call bind() failed, err: %s", strerror(errno)); 207 | goto ERR; 208 | } 209 | s_sock = sock; 210 | 211 | pbase = event_base_new(); 212 | if (NULL == pbase) 213 | { 214 | XL_DEBUG(EN_PRINT_ERROR, "call event_base_new() failed"); 215 | goto ERR; 216 | } 217 | pread_event = event_new(pbase, sock, EV_READ|EV_PERSIST, read_cb, NULL); 218 | if (NULL == pread_event) 219 | { 220 | XL_DEBUG(EN_PRINT_ERROR, "call event_new() failed"); 221 | goto ERR; 222 | } 223 | event_add(pread_event, NULL); 224 | 225 | pping_event = event_new(pbase, -1, EV_TIMEOUT, ping_cb, NULL); 226 | if (NULL == pping_event) 227 | { 228 | XL_DEBUG(EN_PRINT_ERROR, "call event_new() failed"); 229 | goto ERR; 230 | } 231 | event_add(pping_event, &ping_timeout); 232 | event_active(pping_event, EV_TIMEOUT, 0); 233 | 234 | if(s_my_device_sn != 2222) 235 | { 236 | puser_event = event_new(pbase, -1, EV_TIMEOUT, user_cb, NULL); 237 | if (NULL == puser_event) 238 | { 239 | XL_DEBUG(EN_PRINT_ERROR, "call event_new() failed"); 240 | goto ERR; 241 | } 242 | event_add(puser_event, &user_timeout); 243 | } 244 | 245 | XL_DEBUG(EN_PRINT_NOTICE, "sock: %d, enter event_base_dispatch()...", sock); 246 | if (-1 == event_base_dispatch(pbase)) 247 | { 248 | XL_DEBUG(EN_PRINT_ERROR, "call event_base_dispatch() failed"); 249 | goto ERR; 250 | } 251 | XL_DEBUG(EN_PRINT_NOTICE, "exit"); 252 | return 0; 253 | ERR: 254 | return -1; 255 | } -------------------------------------------------------------------------------- /p2p_transfer_udp/p2p_transfer_peer/p2p_transfer_udp_peer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zhangli88/p2p_punch_hole/32fc7f58d921cdebad588e797c6159f890228ad1/p2p_transfer_udp/p2p_transfer_peer/p2p_transfer_udp_peer -------------------------------------------------------------------------------- /p2p_transfer_udp/p2p_transfer_server/Makefile: -------------------------------------------------------------------------------- 1 | all:p2p_transfer_server 2 | 3 | p2p_transfer_server:clean 4 | gcc -o p2p_transfer_server -g -O0 -W -Wall -Werror p2p_transfer_server.c p2p_transfer.c log.c -levent -lm -DNO_SUPPORT_REUSEPORT 5 | clean : 6 | -rm -f p2p_transfer_server 7 | -------------------------------------------------------------------------------- /p2p_transfer_udp/p2p_transfer_server/list.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2011 Felix Fietkau 3 | * Copyright (c) 2010 Isilon Systems, Inc. 4 | * Copyright (c) 2010 iX Systems, Inc. 5 | * Copyright (c) 2010 Panasas, Inc. 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions 10 | * are met: 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice unmodified, this list of conditions, and the following 13 | * disclaimer. 14 | * 2. Redistributions in binary form must reproduce the above copyright 15 | * notice, this list of conditions and the following disclaimer in the 16 | * documentation and/or other materials provided with the distribution. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | #ifndef _LINUX_LIST_H_ 30 | #define _LINUX_LIST_H_ 31 | 32 | #include 33 | #include 34 | 35 | #define prefetch(x) 36 | 37 | #ifndef container_of 38 | #define container_of(ptr, type, member) \ 39 | ({ \ 40 | const typeof(((type *) NULL)->member) *__mptr = (ptr); \ 41 | (type *) ((char *) __mptr - offsetof(type, member)); \ 42 | }) 43 | #endif 44 | 45 | struct list_head 46 | { 47 | struct list_head *next; 48 | struct list_head *prev; 49 | }; 50 | 51 | #define LIST_HEAD_INIT(name) { &(name), &(name) } 52 | #undef LIST_HEAD 53 | #define LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name) 54 | 55 | static inline void 56 | INIT_LIST_HEAD(struct list_head *list) 57 | { 58 | list->next = list->prev = list; 59 | } 60 | 61 | static inline bool 62 | list_empty(const struct list_head *head) 63 | { 64 | return (head->next == head); 65 | } 66 | 67 | static inline bool 68 | list_is_first(const struct list_head *list, 69 | const struct list_head *head) 70 | { 71 | return list->prev == head; 72 | } 73 | 74 | static inline bool 75 | list_is_last(const struct list_head *list, 76 | const struct list_head *head) 77 | { 78 | return list->next == head; 79 | } 80 | 81 | static inline void 82 | _list_del(struct list_head *entry) 83 | { 84 | entry->next->prev = entry->prev; 85 | entry->prev->next = entry->next; 86 | } 87 | 88 | static inline void 89 | list_del(struct list_head *entry) 90 | { 91 | _list_del(entry); 92 | entry->next = entry->prev = NULL; 93 | } 94 | 95 | static inline void 96 | _list_add(struct list_head *_new, struct list_head *prev, 97 | struct list_head *next) 98 | { 99 | 100 | next->prev = _new; 101 | _new->next = next; 102 | _new->prev = prev; 103 | prev->next = _new; 104 | } 105 | 106 | static inline void 107 | list_del_init(struct list_head *entry) 108 | { 109 | _list_del(entry); 110 | INIT_LIST_HEAD(entry); 111 | } 112 | 113 | #define list_entry(ptr, type, field) container_of(ptr, type, field) 114 | #define list_first_entry(ptr, type, field) list_entry((ptr)->next, type, field) 115 | #define list_last_entry(ptr, type, field) list_entry((ptr)->prev, type, field) 116 | 117 | #define list_for_each(p, head) \ 118 | for (p = (head)->next; p != (head); p = p->next) 119 | 120 | #define list_for_each_safe(p, n, head) \ 121 | for (p = (head)->next, n = p->next; p != (head); p = n, n = p->next) 122 | 123 | #define list_for_each_entry(p, h, field) \ 124 | for (p = list_first_entry(h, typeof(*p), field); &p->field != (h); \ 125 | p = list_entry(p->field.next, typeof(*p), field)) 126 | 127 | #define list_for_each_entry_safe(p, n, h, field) \ 128 | for (p = list_first_entry(h, typeof(*p), field), \ 129 | n = list_entry(p->field.next, typeof(*p), field); &p->field != (h);\ 130 | p = n, n = list_entry(n->field.next, typeof(*n), field)) 131 | 132 | #define list_for_each_entry_reverse(p, h, field) \ 133 | for (p = list_last_entry(h, typeof(*p), field); &p->field != (h); \ 134 | p = list_entry(p->field.prev, typeof(*p), field)) 135 | 136 | #define list_for_each_prev(p, h) for (p = (h)->prev; p != (h); p = p->prev) 137 | #define list_for_each_prev_safe(p, n, h) for (p = (h)->prev, n = p->prev; p != (h); p = n, n = p->prev) 138 | 139 | static inline void 140 | list_add(struct list_head *_new, struct list_head *head) 141 | { 142 | _list_add(_new, head, head->next); 143 | } 144 | 145 | static inline void 146 | list_add_tail(struct list_head *_new, struct list_head *head) 147 | { 148 | _list_add(_new, head->prev, head); 149 | } 150 | 151 | static inline void 152 | list_move(struct list_head *list, struct list_head *head) 153 | { 154 | _list_del(list); 155 | list_add(list, head); 156 | } 157 | 158 | static inline void 159 | list_move_tail(struct list_head *entry, struct list_head *head) 160 | { 161 | _list_del(entry); 162 | list_add_tail(entry, head); 163 | } 164 | 165 | static inline void 166 | _list_splice(const struct list_head *list, struct list_head *prev, 167 | struct list_head *next) 168 | { 169 | struct list_head *first; 170 | struct list_head *last; 171 | 172 | if (list_empty(list)) 173 | return; 174 | 175 | first = list->next; 176 | last = list->prev; 177 | first->prev = prev; 178 | prev->next = first; 179 | last->next = next; 180 | next->prev = last; 181 | } 182 | 183 | static inline void 184 | list_splice(const struct list_head *list, struct list_head *head) 185 | { 186 | _list_splice(list, head, head->next); 187 | } 188 | 189 | static inline void 190 | list_splice_tail(struct list_head *list, struct list_head *head) 191 | { 192 | _list_splice(list, head->prev, head); 193 | } 194 | 195 | static inline void 196 | list_splice_init(struct list_head *list, struct list_head *head) 197 | { 198 | _list_splice(list, head, head->next); 199 | INIT_LIST_HEAD(list); 200 | } 201 | 202 | static inline void 203 | list_splice_tail_init(struct list_head *list, struct list_head *head) 204 | { 205 | _list_splice(list, head->prev, head); 206 | INIT_LIST_HEAD(list); 207 | } 208 | 209 | #endif /* _LINUX_LIST_H_ */ 210 | -------------------------------------------------------------------------------- /p2p_transfer_udp/p2p_transfer_server/log.c: -------------------------------------------------------------------------------- 1 | #include "log.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | static const char* LEVEL_NAMES[] = {"DEBUG", "INFO", "NOTICE", "WARN", "ERROR", "FATAL"}; 10 | 11 | static int enable_console = 1; 12 | static FILE *log_stream = NULL; 13 | static int log_level = EN_PRINT_INFO; 14 | 15 | int configure_log(int lvl, const char* file, int use_console) { 16 | FILE *stream = NULL; 17 | int res = 0; 18 | 19 | if (lvl > EN_PRINT_ERROR) 20 | lvl = EN_PRINT_ERROR; 21 | else if (lvl < EN_PRINT_DEBUG) 22 | lvl = EN_PRINT_DEBUG; 23 | log_level = lvl; 24 | enable_console = use_console; 25 | if (file != NULL) { 26 | stream = fopen(file, "a"); 27 | if (stream == NULL) { 28 | XL_DEBUG(EN_PRINT_ERROR, "error opening log file, err: %s", strerror(errno)); 29 | res = 1; 30 | } else { 31 | log_stream = stream; 32 | } 33 | } 34 | 35 | return res; 36 | } 37 | 38 | void destroy_log() 39 | { 40 | if (log_stream != NULL) 41 | { 42 | fclose(log_stream); 43 | } 44 | } 45 | 46 | void logging(int lvl, const char *file, const char *func, const int line, const char *fmt, ...) { 47 | va_list ap; 48 | char buffer[512], *ptr = buffer; 49 | int size, cap = 512; 50 | time_t ts; 51 | struct tm *tmp; 52 | 53 | if (lvl < log_level) { 54 | return; 55 | } 56 | 57 | ts = time(NULL); 58 | tmp = localtime(&ts); 59 | size = strftime(ptr, cap, "[%Y-%m-%d %H:%M:%S]", tmp); 60 | ptr += size; 61 | cap -= size; 62 | size = snprintf(ptr, cap, "[%6s][%s:%d][%s] ", 63 | LEVEL_NAMES[lvl], file, line, func); 64 | ptr += size; 65 | cap -= size; 66 | 67 | va_start(ap, fmt); 68 | size = vsnprintf(ptr, cap, fmt, ap); 69 | va_end(ap); 70 | 71 | *(ptr + size) = '\n'; 72 | *(ptr + size + 1) = '\0'; 73 | 74 | if (enable_console) { 75 | if (lvl >= EN_PRINT_WARN) { 76 | fputs(buffer, stderr); 77 | } else { 78 | fputs(buffer, stdout); 79 | } 80 | } 81 | 82 | if (log_stream != NULL) { 83 | fputs(buffer, log_stream); 84 | fflush(log_stream); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /p2p_transfer_udp/p2p_transfer_server/log.h: -------------------------------------------------------------------------------- 1 | #ifndef __LOG_H_ 2 | #define __LOG_H_ 3 | 4 | enum _log_level { 5 | EN_PRINT_DEBUG, 6 | EN_PRINT_INFO, 7 | EN_PRINT_NOTICE, 8 | EN_PRINT_WARN, 9 | EN_PRINT_ERROR, 10 | EN_PRINT_FATAL, 11 | }; 12 | 13 | int configure_log(int level, const char* file, int use_console); 14 | void destroy_log(); 15 | 16 | void logging(int lvl, const char *file, const char *func, const int line, const char *fmt, ...); 17 | 18 | #define XL_DEBUG(lvl, fmt, ...) logging(lvl, __FILE__, __FUNCTION__, __LINE__, fmt, ##__VA_ARGS__) 19 | 20 | #endif /* __LOG_H_ */ 21 | -------------------------------------------------------------------------------- /p2p_transfer_udp/p2p_transfer_server/p2p_transfer.c: -------------------------------------------------------------------------------- 1 | #include "p2p_transfer.h" 2 | #include "log.h" 3 | #include 4 | #include 5 | #include 6 | 7 | const char *get_string_network_type(int network_type) 8 | { 9 | static char *s_network_type[] = { 10 | "UNKNOWN", 11 | "PUBLIC_NETWORK", 12 | "FULL_CONE_NAT", 13 | "RESTRICTED_CONE_NAT", 14 | "PORT_RESTRICTED_CONE_NAT", 15 | "SYMMETRIC_NAT", 16 | }; 17 | if (network_type < NP_UNKNOWN || network_type > NP_SYMMETRIC_NAT) 18 | { 19 | network_type = NP_UNKNOWN; 20 | } 21 | return s_network_type[network_type]; 22 | } 23 | 24 | int set_sock_opt(int sock, int flag) 25 | { 26 | int enable = 1; 27 | 28 | if (flag & SO_REUSEADDR) 29 | { 30 | if (-1 == setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable))) 31 | { 32 | XL_DEBUG(EN_PRINT_ERROR, "call setsockopt() failed, set SO_REUSEPORT failed, err: %s", strerror(errno)); 33 | return -1; 34 | } 35 | else 36 | { 37 | XL_DEBUG(EN_PRINT_ERROR, "set SO_REUSEPORT success"); 38 | } 39 | } 40 | #ifndef NO_SUPPORT_REUSEPORT 41 | if (flag & SO_REUSEPORT) 42 | { 43 | if (-1 == setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(enable))) 44 | { 45 | XL_DEBUG(EN_PRINT_ERROR, "call setsockopt() failed, set SO_REUSEPORT failed, err: %s", strerror(errno)); 46 | return -1; 47 | } 48 | } 49 | #endif 50 | if (flag & SO_KEEPALIVE) 51 | { 52 | if (-1 == setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable))) 53 | { 54 | XL_DEBUG(EN_PRINT_ERROR, "call setsockopt() failed, set SO_KEEPALIVE failed, err: %s", strerror(errno)); 55 | return -1; 56 | } 57 | } 58 | return 0; 59 | } 60 | 61 | void generate_server_addr(struct sockaddr_in *paddr) 62 | { 63 | assert(paddr != NULL); 64 | 65 | memset(paddr, 0, sizeof(*paddr)); 66 | paddr->sin_family = AF_INET; 67 | paddr->sin_addr.s_addr = inet_addr(P2P_TRANSFER_SERVER_IP); 68 | paddr->sin_port = htons(P2P_TRANSFER_SERVER_PORT); 69 | } 70 | 71 | void generate_peer_addr(struct sockaddr_in *paddr, const struct p2p_msg_device_info_t *pdevice_info) 72 | { 73 | assert(paddr != NULL); 74 | assert(pdevice_info != NULL); 75 | 76 | memset(paddr, 0, sizeof(*paddr)); 77 | paddr->sin_family = AF_INET; 78 | paddr->sin_addr = pdevice_info->ip_addr; 79 | paddr->sin_port = pdevice_info->port; 80 | XL_DEBUG(EN_PRINT_DEBUG, "ip: %s, port: %d", inet_ntoa(paddr->sin_addr), ntohs(paddr->sin_port)); 81 | } 82 | 83 | const char *get_string_cmd(int cmd) 84 | { 85 | static char *s_cmd[] = { 86 | "P2P_TRANSFER_UNKNOWN_CMD", 87 | "P2P_TRANSFER_PING", 88 | "P2P_TRANSFER_QUERY_DEVICE_INFO_REQUEST", 89 | "P2P_TRANSFER_QUERY_DEVICE_INFO_RESPONSE", 90 | "P2P_TRANSFER_PUNCH_HOLE", 91 | "P2P_TRANSFER_PUNCH_HOLE_TO_PEER", 92 | "P2P_TRANSFER_USER_DATA", 93 | }; 94 | if (cmd < P2P_TRANSFER_UNKNOWN_CMD || cmd > P2P_TRANSFER_USER_DATA) 95 | { 96 | cmd = P2P_TRANSFER_UNKNOWN_CMD; 97 | } 98 | return s_cmd[cmd]; 99 | } -------------------------------------------------------------------------------- /p2p_transfer_udp/p2p_transfer_server/p2p_transfer.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zhangli88/p2p_punch_hole/32fc7f58d921cdebad588e797c6159f890228ad1/p2p_transfer_udp/p2p_transfer_server/p2p_transfer.h -------------------------------------------------------------------------------- /p2p_transfer_udp/p2p_transfer_server/p2p_transfer_server: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zhangli88/p2p_punch_hole/32fc7f58d921cdebad588e797c6159f890228ad1/p2p_transfer_udp/p2p_transfer_server/p2p_transfer_server -------------------------------------------------------------------------------- /p2p_transfer_udp/p2p_transfer_server/p2p_transfer_server.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zhangli88/p2p_punch_hole/32fc7f58d921cdebad588e797c6159f890228ad1/p2p_transfer_udp/p2p_transfer_server/p2p_transfer_server.c --------------------------------------------------------------------------------