UDP relay的代码基本都在udprelay.c中,无论ss-local还是ss-server的代码都在一起,使用宏MODULE_LOCAL,MODULE_REMOTE等区分开。代码虽然不是很多,但是由于ss-local和ss-server以及ss-redir,ss-tunnel等夹杂在同一个函数中,不断有宏去打断读代码的思路,并且很多代码还是同时被ss-local和ss-server执行到,所以本系列分多篇去逐个分析重要的函数。先从init_udprelay开始。

* init_udprelay函数声明:

int
init_udprelay(const char *server_host, const char *server_port,
#ifdef MODULE_LOCAL
              const struct sockaddr *remote_addr, const int remote_addr_len,
#ifdef MODULE_TUNNEL
              const ss_addr_t tunnel_addr,
#endif
#endif
              int mtu, crypto_t *crypto, int timeout, const char *iface)

对于ss-local,多出两个参数,即remote_addr和remote_addr_len。

这个就是要使用的ss-server的地址,通过参数传进来。而ss-server不需要指定外发地址,因为ss-server外发udp的地址是从ss udp包的addr header里面读取到的。

* init_udprelay函数解析: 初始化udp relay,主要是创建server socket (无论ss-local还是ss-server,用于接收来自前端的udp数据,对于ss-local就是接收客户端的udp数据,对于ss-server,就是接收ss-local发送过来的udp); 另外还创建了一个server_ctx_t对象,用于存放udp server相关的一些信息。这个server_ctx保存了server fd等内容,会在后续方法中使用到,比较重要。

typedef struct server_ctx {
    ev_io io;
    int fd;
    crypto_t *crypto;
    int timeout;
    const char *iface;
    struct cache *conn_cache;
#ifdef MODULE_LOCAL
    const struct sockaddr *remote_addr;
    int remote_addr_len;
#ifdef MODULE_TUNNEL
    ss_addr_t tunnel_addr;
#endif
#endif
#ifdef MODULE_REMOTE
    struct ev_loop *loop;
#endif
} server_ctx_t;

下面列出init_udprelay的重要步骤:

* create_server_socket 创建socket并bind,返回fd

* setnonblocking(serverfd);设为非阻塞

* new_server_ctx(serverfd)创建server_ctx_t对象,然后设置属性:

* ev_io_init(&ctx->io, server_recv_cb, fd, EV_READ); 设置fd的读事件回调为server_recv_cb

* server_ctx->timeout = max(timeout, MIN_UDP_TIMEOUT); 设置timeout至少为MIN_UDP_TIMEOUT即10秒

* server_ctx->conn_cache = conn_cache; 设置cache。cache的创建如下:

struct cache *conn_cache;
    cache_create(&conn_cache, MAX_UDP_CONN_NUM, free_cb);
  • 如果是ss-local,设置remote addr:
#ifdef MODULE_LOCAL
    server_ctx->remote_addr     = remote_addr;
    server_ctx->remote_addr_len = remote_addr_len;
  • ev_io_start(loop, &server_ctx->io); 启动fd上读事件的监听
  • 最后返回创建好的serverfd: 对于ss-local,返回的fd被用于通过socks5 response返回给socks5客户端,socks5客户端根据这个fd获取udp server的端口号(因为将ss作为一个Lib使用时,有可能让系统动态选择端口号)。而ss-server是不使用这个返回的fd的。
  • init_udprelay执行完成之后,udp server就开始等待读取来自前端的udp数据了,即有数据可接收时,server_recv_cb会被调用。(注:这儿使用前端是因为在同时讨论ss-local和ss-server,对于local前端即客户端,对于server前端即local,下同)

最新文章

  1. mysql 简单练习
  2. josephus Problem 中级(使用数组模拟链表,提升效率)
  3. mysql笔记04 MySQL高级特性
  4. IOS源码封装成.bundle和.a文件,以及加入xib的具体方法,翻遍网络,仅此一家完美翻译!! IOS7!!(3) 完美结局
  5. ubuntu启动失败the system is running in low graphics mode
  6. 线程-run和start
  7. Flask architecture
  8. 【Java框架型项目从入门到装逼】第六节 - 用ajax请求后台数据
  9. OpenCV3.4两种立体匹配算法效果对比
  10. 【Unity与23种设计模式】责任链模式(Chain of Responsibility)
  11. VK-Cup2017 Wild Card Round 2
  12. 收集整理的一些c++书籍(推荐)
  13. HTML文档结构
  14. Golang基础语法1
  15. 在UnrealEngine中用Custom节点实现高斯模糊
  16. 转 Configuring Relationships with the Fluent API
  17. 集合类(常见的集合类:Collection、List、Set、ArrayList、linkedList、Vector、HashSet、TreeSet)
  18. RabbitMQ消费方式汇总
  19. How Autofs Works
  20. 浅谈App原生开发、混合开发及HTML5开发的优劣

热门文章

  1. SpringBoot 简单集成ActiveMQ
  2. uboot下ext4ls的用法
  3. Pandas 数据分析基础
  4. CentOS7配置自定义JDK
  5. VS2012 QT5.2.0 无法解析的外部符号
  6. JavaScript高级程序设计-读书笔记(6)
  7. 微信公众平台开发(一) 配置接口与验证URL
  8. JSP 国际化
  9. Dubbo本地开发技巧
  10. C++调用Python脚本中的函数