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,下同)

ss-libev 源码解析udp篇 (2)的更多相关文章

  1. ss-libev 源码解析udp篇 (4)

    本篇分析remote_recv_cb,这是整个udp转发的反方向,即读取从后端发送过来的数据再发送给前端.对于ss-server,读取到的数据是目标地址的udp服务器发送回来的响应数据,ss-serv ...

  2. ss-libev 源码解析udp篇 (3)

    本篇分析server_recv_cb,这个是udp转发中最重要的函数. server_recv_cb: 当ss-local或ss-server接收到来自前端的udp数据包时调用.这个函数代码比较多,除 ...

  3. ss-libev 源码解析udp篇 (1)

    shadowsocks-libev udp转发原理简介 ss_local作为一个sock5服务器,接收来自socks5客户端的数据包.在ss_local启动后,即创建一个udp socket,并bin ...

  4. jQuery2.x源码解析(缓存篇)

    jQuery2.x源码解析(构建篇) jQuery2.x源码解析(设计篇) jQuery2.x源码解析(回调篇) jQuery2.x源码解析(缓存篇) 缓存是jQuery中的又一核心设计,jQuery ...

  5. jQuery2.x源码解析(构建篇)

    jQuery2.x源码解析(构建篇) jQuery2.x源码解析(设计篇) jQuery2.x源码解析(回调篇) jQuery2.x源码解析(缓存篇) 笔者阅读了园友艾伦 Aaron的系列博客< ...

  6. jQuery2.x源码解析(设计篇)

    jQuery2.x源码解析(构建篇) jQuery2.x源码解析(设计篇) jQuery2.x源码解析(回调篇) jQuery2.x源码解析(缓存篇) 这一篇笔者主要以设计的角度探索jQuery的源代 ...

  7. jQuery2.x源码解析(回调篇)

    jQuery2.x源码解析(构建篇) jQuery2.x源码解析(设计篇) jQuery2.x源码解析(回调篇) jQuery2.x源码解析(缓存篇) 通过艾伦的博客,我们能看出,jQuery的pro ...

  8. Shiro源码解析-Session篇

    上一篇Shiro源码解析-登录篇中提到了在登录验证成功后有对session的处理,但未详细分析,本文对此部分源码详细分析下. 1. 分析切入点:DefaultSecurityManger的login方 ...

  9. myBatis源码解析-类型转换篇(5)

    前言 开始分析Type包前,说明下使用场景.数据构建语句使用PreparedStatement,需要输入的是jdbc类型,但我们一般写的是java类型.同理,数据库结果集返回的是jdbc类型,而我们需 ...

随机推荐

  1. Maven取消编译自动测试

    Maven取消编译自动测试 <build> <plugins> <plugin> <groupId>org.apache.maven.plugins&l ...

  2. 搭建ODS的几套解决方案对比

    公司业务,想要搭建一个医院的ODS服务器:将医院不同厂家的不同数据库版本数据库类型整到一台服务器中,最初想要是同步数据库原生同步机制,最理想的是sqlserver发布订阅,但是后来发现发布订阅不能发布 ...

  3. Mysql MariaDB安装

    1.安装 本人使用的是CentOS 7 ,默认yum安装,但默认yum安装版本有点低,可根据需要选择升级,我这里选择先升级再安装. 更新yum //更新yum包 yum -y update 配置yum ...

  4. java程序结构

    if....else.... 1.  if都需要接判断表达式 2.  else不需要表达式 3. 有if没else可以,但else必须要有一个if,if数>=else数 if (A条件)     ...

  5. 如何将本地的项目上传到git

    如何将本地的项目上传到git 1 进入项目文件夹,把目录变为git仓库 git init 2 把文件添加到版本库中 git add . 3 把版本提交到版本库 git commit -m 'first ...

  6. LeetCode第[88]题(Java):Merge Sorted Array(合并已排序数组)

    题目:合并已排序数组 难度:Easy 题目内容: Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as ...

  7. sina sae搭建wordpress数据库配置

    sina app engine上搭建wordpress,使用快速安装向导会无法连接数据库. 可以在本地修改好 wp-config.php再提交. <?php /** * WordPress 基础 ...

  8. Mysql5.7基于事务转为基于日志

    先决条件 master端执行 flush logs;show master status; 获取file和position slave端执行 stop slave; change master to ...

  9. 搞懂分布式技术12:分布式ID生成方案

    搞懂分布式技术12:分布式ID生成方案 ## 转自: 58沈剑 架构师之路 2017-06-25 一.需求缘起 几乎所有的业务系统,都有生成一个唯一记录标识的需求,例如: 消息标识:message-i ...

  10. JavaScript中Function Declaration与Function Expression 或者说 function fn(){}和var fn=function(){} 的区别

    JavaScript是一种解释型语言,函数声明会在JavaScript代码加载后.执行前被解释,而函数表达式只有在执行到这一行代码时才会被解释. 在JS中有两种定义函数的方式, 1是:var aaa= ...