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. Tomcat热部署,Web工程中线程没有终止

    近期项目中,用 jenkins 热部署 web工程时,发现工程中静态持有的线程(将ScheduledExecutorService定时任务存储在静态Map中),导致不定时出现数据库访问事务关闭异常,如 ...

  2. HTTP-java访问https资源时,忽略证书信任问题,代码栗子

    java程序在访问https资源时,出现报错 sun.security.validator.ValidatorException: PKIX path building failed: sun.sec ...

  3. springmvc.xml配置图解

  4. hadoop随手笔记

    1.Hadoop Streaming 是为了方便不太熟悉java用户编写MR程序的工具.用户可以将任何可执行文件(C++)或者脚本(python,ruby)作为Mapper/Reducer, 提高了效 ...

  5. 在eclipse搭建python开发环境

    在一次看别人帖子的时候发现,别人是用eclipse来写python代码的,所以好奇也想尝试一番,之前一直在用Pycharm,这个也确实是最好的开发python的IDE了,但是有时候也会有卡顿的情况,主 ...

  6. 百度开源分布式id生成器uid-generator源码剖析

    百度uid-generator源码 https://github.com/baidu/uid-generator snowflake算法 uid-generator是基于Twitter开源的snowf ...

  7. win10家庭版的defender注册表关闭和开启

    关闭方法: 打开“命令提示符(管理员)”,然后输入: reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows Defe ...

  8. 永久更改hostname主机名

    vim /etc/sysconfig/network NETWORKING=yesHOSTNAME=keepalived-nginx1GATEWAY=192.168.33.2 vim /etc/hos ...

  9. ASP.NET OAuth Authorization - Difference between using ClientId and Secret and Username and Password

      What I don't fully understand is the use of ClientId and Secret vs Username and Password. The code ...

  10. Basic Authentication in ASP.NET Web API

    Basic authentication is defined in RFC 2617, HTTP Authentication: Basic and Digest Access Authentica ...