📄 su_proxy.c
字号:
/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi <pekka.pessi@nokia.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * *//**@ingroup su_root_ex * * @file su_proxy.c * * @brief Transport level proxy demonstrating various @b su features. * * @author Pekka Pessi <Pekka.Pessi@nokia.com> * * @date Created: Wed May 23 17:42:40 2001 ppessi */#include "config.h"#include <stdio.h>#include <string.h>#include <stdlib.h>#include <stddef.h>#include <errno.h>#include <assert.h>typedef struct proxy_s proxy_t;typedef struct forwarder_s forwarder_t;typedef struct buffer_s buffer_t;#define SU_ROOT_MAGIC_T proxy_t#define SU_MSG_ARG_T su_socket_t#define SU_WAKEUP_ARG_T forwarder_t#include "sofia-sip/su.h"#include "sofia-sip/su_wait.h"#include "sofia-sip/su_alloc.h"#include "su_module_debug.h"#if HAVE_FUNC#elif HAVE_FUNCTION#define __func__ __FUNCTION__#else#define __func__ "su_proxy"#endifstruct proxy_s { su_home_t pr_home[1]; su_root_t *pr_root; su_addrinfo_t *pr_addrinfo; forwarder_t *pr_forwarders;};struct forwarder_s { forwarder_t *f_next; forwarder_t **f_prev; proxy_t *f_pr; su_socket_t f_socket; su_wait_t f_wait[2]; forwarder_t *f_peer; su_sockaddr_t f_dest[1]; buffer_t *f_buf; unsigned long f_sent; /* bytes sent */ unsigned f_shutdown : 1; unsigned f_upstream : 1;};struct buffer_s{ buffer_t *b_next; buffer_t **b_prev; int b_sent; int b_used; char b_data[8192];};char const help[] ="usage: su_proxy [-ntu] remotehost remoteport [localport]\n";void usage(void){ fputs(help, stderr);}static int pr_init(proxy_t *pr);static int pr_config(proxy_t *pr, int argc, char *argv[]);static int pr_run(proxy_t *pr);static void pr_deinit(proxy_t *pr);static forwarder_t *forwarder_create(proxy_t *pr);static forwarder_t *forwarder_create_listener(proxy_t *pr, su_addrinfo_t *ai);static void forwarder_deinit(forwarder_t *f);static int forwarder_init_stream(forwarder_t *f);static int forwarder_init_dgram(forwarder_t *f);static int forwarder_accept(proxy_t *pr, su_wait_t *w, forwarder_t *f);static int forwarder_stream_peer(proxy_t *pr, forwarder_t *f);static int forwarder_connected(proxy_t *pr, su_wait_t *w, forwarder_t *f);static int forwarder_recv(proxy_t *pr, su_wait_t *w, forwarder_t *f);static int forwarder_send(proxy_t *pr, forwarder_t *f, buffer_t *b);static int forwarder_append(forwarder_t *f, buffer_t *b0);static int forwarder_empty(proxy_t *pr, su_wait_t *w, forwarder_t *f);static int forwarder_shutdown(forwarder_t *f);static void forwarder_close(forwarder_t *f1);int main(int argc, char *argv[]){ proxy_t pr[1] = {{{ SU_HOME_INIT(pr) }}}; int error; error = pr_init(pr); if (error == 0) { if ((error = pr_config(pr, argc, argv)) > 1) usage(); } if (error == 0) error = pr_run(pr); pr_deinit(pr); su_deinit(); exit(error);}int pr_init(proxy_t *pr){ su_init(); su_home_init(pr->pr_home); pr->pr_root = su_root_create(pr); return pr->pr_root ? 0 : 1;}int pr_config(proxy_t *pr, int argc, char *argv[]){ su_addrinfo_t *res = NULL, *ai, hints[1] = {{ 0 }}; char *service; int error; char const *option; /* char const *argv0 = argv[0]; */ while (argv[1][0] == '-') { option = argv[1]; argv++, argc--; if (strcmp(option, "--") == 0) break; else if (strcmp(option, "-n") == 0) { hints->ai_flags |= AI_NUMERICHOST; } else if (strcmp(option, "-d") == 0) { hints->ai_socktype = SOCK_DGRAM; } else if (strcmp(option, "-s") == 0) { hints->ai_socktype = SOCK_STREAM; } else if (strcmp(option, "-4") == 0) { hints->ai_family = AF_INET; }#if SU_HAVE_IN6 else if (strcmp(option, "-6") == 0) { hints->ai_family = AF_INET6; }#endif } if (argc < 3) return 2; if ((error = su_getaddrinfo(argv[1], argv[2], hints, &res))) { fprintf(stderr, "getaddrinfo: %s:%s: %s\n", argv[1], argv[2], su_gai_strerror(error)); return 1; } pr->pr_addrinfo = res; if (argv[3]) service = argv[3]; else service = argv[2]; hints->ai_flags |= AI_PASSIVE; if ((error = su_getaddrinfo(NULL, service, hints, &res))) { fprintf(stderr, "getaddrinfo: %s: %s\n", service, su_gai_strerror(error)); return 1; } for (ai = res; ai; ai = ai->ai_next) { forwarder_create_listener(pr, ai); } su_freeaddrinfo(res); if (!pr->pr_forwarders) { fprintf(stderr, "%s:%s: %s\n", argv[1], argv[2], "unable to forward"); return 1; } return 0;}void pr_deinit(proxy_t *pr){ if (pr->pr_addrinfo) su_freeaddrinfo(pr->pr_addrinfo), pr->pr_addrinfo = NULL; if (pr->pr_root) su_root_destroy(pr->pr_root), pr->pr_root = NULL; su_home_deinit(pr->pr_home); su_deinit();}static int pr_run(proxy_t *pr){ su_root_run(pr->pr_root); return 0;}forwarder_t *forwarder_create(proxy_t *pr){ forwarder_t *f; assert(pr); f = su_zalloc(pr->pr_home, sizeof (*f)); if (f) { f->f_socket = INVALID_SOCKET; su_wait_init(f->f_wait); su_wait_init(f->f_wait + 1); f->f_pr = pr; if ((f->f_next = pr->pr_forwarders)) f->f_next->f_prev = &f->f_next; f->f_prev = &pr->pr_forwarders; pr->pr_forwarders = f; } return f;}void forwarder_destroy(forwarder_t *f){ if (f) { forwarder_deinit(f); if (f->f_peer) { f->f_peer->f_peer = NULL; forwarder_destroy(f->f_peer); f->f_peer = NULL; } assert(f->f_prev); if ((*f->f_prev = f->f_next)) f->f_next->f_prev = f->f_prev; su_free(f->f_pr->pr_home, f); }}void forwarder_deinit(forwarder_t *f){ su_root_unregister(f->f_pr->pr_root, f->f_wait, NULL, f); su_wait_destroy(f->f_wait); su_root_unregister(f->f_pr->pr_root, f->f_wait + 1, NULL, f); su_wait_destroy(f->f_wait + 1); if (f->f_socket != INVALID_SOCKET) su_close(f->f_socket), f->f_socket = INVALID_SOCKET; if (f->f_buf) su_free(f->f_pr->pr_home, f->f_buf), f->f_buf = NULL;}static forwarder_t *forwarder_create_listener(proxy_t *pr, su_addrinfo_t *ai){ forwarder_t *f; su_socket_t s; if (ai->ai_socktype != SOCK_STREAM && ai->ai_socktype != SOCK_DGRAM) return NULL; f = forwarder_create(pr); if (f) { s = su_socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (s != INVALID_SOCKET) { f->f_socket = s; su_setblocking(s, 0); su_setreuseaddr(s, 1); if (bind(s, ai->ai_addr, ai->ai_addrlen) >= 0) { if (ai->ai_socktype == SOCK_STREAM ? forwarder_init_stream(f) >= 0 : forwarder_init_dgram(f) >= 0) return f; } else { SU_DEBUG_1(("%s: bind: %s\n", __func__, su_strerror(su_errno()))); } } } forwarder_destroy(f); return NULL;}int forwarder_init_stream(forwarder_t *f){ if (listen(f->f_socket, SOMAXCONN) < 0) return SOCKET_ERROR;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -