查看: 5020|回复: 2

分析openwrt uhttpd代码

[复制链接]
  • TA的每日心情
    开心
    2016-8-15 09:30
  • 签到天数: 162 天

    连续签到: 1 天

    [LV.7]常住居民III

    发表于 2017-7-17 13:54:08 | 显示全部楼层 |阅读模式
    分享到:

    主函数:
    1. int main(int argc, char **argv)
    2. {
    3.     struct alias *alias;
    4.     /* 设置命令的别名
    5.     struct alias {
    6.         struct list_head list;//命令列表
    7.         char *alias;//命令别名
    8.         char *path;//命令路径
    9.     };
    10.    
    11.     struct list_head {
    12.         struct list_head *next;//列表下一个对象
    13.         struct list_head *prev;//列表前一个对象
    14.     };
    15.      */

    16.     bool nofork = false;
    17.     /* 进程还没有开始克隆自己 */

    18.     char *port;
    19.     /* 端口 */

    20.     int opt;
    21.     /* 一个在for里面使用的普通变量 */
    22.    
    23.     int ch;
    24.     /* 一个在while里面使用的普通变量 */

    25.     int cur_fd;
    26.     /* 保存了"/dev/null"句柄 */

    27.     int bound = 0;
    28.     /* 绑定的监听端口个数 */

    29. #ifdef HAVE_TLS
    30. /* 当安装了tls插件 */

    31.     int n_tls = 0;
    32.     /* 如果安装了tls,则不为0 */

    33.     const char *tls_key = NULL;
    34.     /* ASN.1 server private key file */
    35.    
    36.     const char *tls_crt = NULL;
    37.     /* ASN.1 server certificate file */

    38. #endif

    39.     BUILD_BUG_ON(sizeof(uh_buf) < PATH_MAX); /* 条件为真,编译报错,uh_buf为4096,path_max一般为260 */
    40.     /*
    41.     #define __BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
    42.     */

    43.     uh_dispatch_add(&cgi_dispatch);
    44.     /*
    45.     添加cgi调度程序到双向链表
    46.     */
    47.    
    48.     init_defaults_pre();
    49.     /*
    50.     初始化配置变量
    51.     */
    52.    
    53.     signal(SIGPIPE, SIG_IGN);
    54.     /*
    55.     函数原型:sig_t signal(int signum,sig_t handler);
    56.     功能:设置某一信号的对应动作
    57.     第一个参数signum指明了所要处理的信号类型,它可以取除了SIGKILL和SIGSTOP外的任何一种信号。
    58.     第二个参数handler描述了与信号关联的动作。
    59.     SIGPIPE:在reader中止之后写Pipe的时候发送
    60.     SIG_IGN:表示忽略该信号
    61.     函数说明:
    62.         signal()会依参数signum 指定的信号编号来设置该信号的处理函数。
    63.         当指定的信号到达时就会跳转到参数handler指定的函数执行。
    64.         当一个信号的信号处理函数执行时,如果进程又接收到了该信号,
    65.         该信号会自动被储存而不会中断信号处理函数的执行,直到信号处理函数执行完毕再重新调用相应的处理函数。
    66.         但是如果在信号处理函数执行时进程收到了其它类型的信号,该函数的执行就会被中断。
    67.     */


    68.     /*
    69.     原型:int getopt(int argc,char * const argv[ ],const char * optstring);
    70.     功能:用来分析命令行参数。
    71.     参数:argc和argv是由main()传递的参数个数和内容。参数optstring则代表欲处理的选项字符串。
    72.     函数说明:此函数会返回在argv 中下一个的选项字母,此字母会对应参数optstring 中的字母。
    73.             如果选项字符串里的字母后接着冒号“:”,则表示还有相关的参数,全域变量optarg 即会指向此额外参数。
    74.             如果getopt()找不到符合的参数则会印出错信息,并将全域变量optopt设为“?”字符,
    75.             如果不希望getopt()印出错信息,则只要将全域变量opterr设为0即可。
    76.     */
    77.    
    78.     while (ch = getopt(argc, argv, "A:aC:c:Dd:E:fh:H:I:i:K:k:L:l:m:N:n:p:qRr:Ss:T:t:U:u:Xx:y:") != -1)
    79.     {
    80.         /*
    81.         每次解释一个命令行传递过来的参数
    82.         */
    83.         
    84.         switch(ch)
    85.         {
    86.         
    87. #ifdef HAVE_TLS
    88. /* 如果安装了tls插件,命令行又带相关的参数,执行相应的配置 */
    89.         case 'C':
    90.             tls_crt = optarg;
    91.             break;

    92.         case 'K':
    93.             tls_key = optarg;
    94.             break;

    95.         case 'q':
    96.             conf.tls_redirect = 1;
    97.             break;

    98.         case 's':
    99.             n_tls++;
    100.             /* fall through */
    101. #else
    102. /* 如果没有安装tls插件,命令行又带相关的参数,显示错误 ,但继续执行*/
    103.         case 'C':
    104.         case 'K':
    105.         case 'q':
    106.         case 's':
    107.             fprintf(stderr, "uhttpd: TLS support not compiled, "
    108.                             "ignoring -%c\n", ch);
    109.             break;
    110. #endif

    111.         case 'p':
    112.             optarg = strdup(optarg);
    113.             bound += add_listener_arg(optarg, (ch == 's'));
    114.             break;

    115.         case 'h':
    116.             if (!realpath(optarg, uh_buf))
    117.             {
    118.                 fprintf(stderr, "Error: Invalid directory %s: %s\n",
    119.                         optarg, strerror(errno));
    120.                 exit(1);
    121.             }
    122.             conf.docroot = strdup(uh_buf);
    123.             break;

    124.         case 'H':
    125.             if (uh_handler_add(optarg))
    126.             {
    127.                 fprintf(stderr, "Error: Failed to load handler script %s\n",
    128.                     optarg);
    129.                 exit(1);
    130.             }
    131.             break;

    132.         case 'E':
    133.             if (optarg[0] != '/')
    134.             {
    135.                 fprintf(stderr, "Error: Invalid error handler: %s\n",
    136.                         optarg);
    137.                 exit(1);
    138.             }
    139.             conf.error_handler = optarg;
    140.             break;

    141.         case 'I':
    142.             if (optarg[0] == '/')
    143.             {
    144.                 fprintf(stderr, "Error: Invalid index page: %s\n",
    145.                         optarg);
    146.                 exit(1);
    147.             }
    148.             uh_index_add(optarg);
    149.             break;

    150.         case 'S':
    151.             conf.no_symlinks = 1;
    152.             break;

    153.         case 'D':
    154.             conf.no_dirlists = 1;
    155.             break;

    156.         case 'R':
    157.             conf.rfc1918_filter = 1;
    158.             break;

    159.         case 'n':
    160.             conf.max_script_requests = atoi(optarg);
    161.             break;

    162.         case 'N':
    163.             conf.max_connections = atoi(optarg);
    164.             break;

    165.         case 'x':
    166.             fixup_prefix(optarg);
    167.             conf.cgi_prefix = optarg;
    168.             break;

    169.         case 'y':
    170.             alias = calloc(1, sizeof(*alias));
    171.             if (!alias)
    172.             {
    173.                 fprintf(stderr, "Error: failed to allocate alias\n");
    174.                 exit(1);
    175.             }
    176.             alias->alias = strdup(optarg);
    177.             alias->path = strchr(alias->alias, '=');
    178.             if (alias->path)
    179.                 *alias->path++ = 0;
    180.             list_add(&alias->list, &conf.cgi_alias);
    181.             break;

    182.         case 'i':
    183.             optarg = strdup(optarg);
    184.             port = strchr(optarg, '=');
    185.             if (optarg[0] != '.' || !port)
    186.             {
    187.                 fprintf(stderr, "Error: Invalid interpreter: %s\n",
    188.                         optarg);
    189.                 exit(1);
    190.             }

    191.             *port++ = 0;
    192.             uh_interpreter_add(optarg, port);
    193.             break;

    194.         case 't':
    195.             conf.script_timeout = atoi(optarg);
    196.             break;

    197.         case 'T':
    198.             conf.network_timeout = atoi(optarg);
    199.             break;

    200.         case 'k':
    201.             conf.http_keepalive = atoi(optarg);
    202.             break;

    203.         case 'A':
    204.             conf.tcp_keepalive = atoi(optarg);
    205.             break;

    206.         case 'f':
    207.             nofork = 1;
    208.             break;

    209.         case 'd':
    210.             optarg = strdup(optarg);
    211.             port = alloca(strlen(optarg) + 1);
    212.             if (!port)
    213.                 return -1;

    214.             /* "decode" plus to space to retain compat */
    215.             for (opt = 0; optarg[opt]; opt++)
    216.                 if (optarg[opt] == '+')
    217.                     optarg[opt] = ' ';

    218.             /* opt now contains strlen(optarg) -- no need to re-scan */
    219.             if (uh_urldecode(port, opt, optarg, opt) < 0)
    220.             {
    221.                 fprintf(stderr, "uhttpd: invalid encoding\n");
    222.                 return -1;
    223.             }

    224.             printf("%s", port);
    225.             return 0;
    226.             break;

    227.         /* basic auth realm */
    228.         case 'r':
    229.             conf.realm = optarg;
    230.             break;

    231.         /* md5 crypt */
    232.         case 'm':
    233.             printf("%s\n", crypt(optarg, "$1$"));
    234.             return 0;
    235.             break;

    236.         /* config file */
    237.         case 'c':
    238.             conf.file = optarg;
    239.             break;

    240. #ifdef HAVE_LUA
    241. /* 如果安装了lua插件,命令行又带相关的参数,执行相应的配置 */
    242.         case 'l':
    243.             conf.lua_prefix = optarg;
    244.             break;

    245.         case 'L':
    246.             conf.lua_handler = optarg;
    247.             break;
    248. #else
    249. /* 如果没有安装lua插件,命令行又带相关的参数,显示错误 ,但继续执行*/
    250.         case 'l':
    251.         case 'L':
    252.             fprintf(stderr, "uhttpd: Lua support not compiled, "
    253.                             "ignoring -%c\n", ch);
    254.             break;
    255. #endif

    256. #ifdef HAVE_UBUS
    257. /* 如果安装了ubus插件,命令行又带相关的参数,执行相应的配置 */
    258.         case 'a':
    259.             conf.ubus_noauth = 1;
    260.             break;

    261.         case 'u':
    262.             conf.ubus_prefix = optarg;
    263.             break;

    264.         case 'U':
    265.             conf.ubus_socket = optarg;
    266.             break;

    267.         case 'X':
    268.             conf.ubus_cors = 1;
    269.             break;
    270. #else
    271. /* 如果没有安装ubus插件,命令行又带相关的参数,显示错误 ,但继续执行*/
    272.         case 'a':
    273.         case 'u':
    274.         case 'U':
    275.         case 'X':
    276.             fprintf(stderr, "uhttpd: UBUS support not compiled, "
    277.                             "ignoring -%c\n", ch);
    278.             break;
    279. #endif

    280.         default:
    281.             return usage(argv[0]);
    282.             /* 没有参数或者有不明参数,显示帮助并退出 */
    283.         }
    284.     }

    285.     uh_config_parse();
    286.     /*
    287.     原型:static void uh_config_parse(void)
    288.     功能:解析config文件
    289.     */

    290.     if (!conf.docroot) /* 如果conf结构体里的docroot还没有赋值,就执行 */
    291.     {
    292.         if (!realpath(".", uh_buf)) /* uh_buf为当前工作目录的绝对路径指针 */
    293.         {
    294.             /*
    295.             原型:char *realpath(const char *path, char *resolved_path);
    296.             功能:用来将参数path所指的相对路径转换成绝对路径
    297.             返回值:成功则返回指向resolved_path的指针,失败返回NULL
    298.             */
    299.             fprintf(stderr, "Error: Unable to determine work dir\n");
    300.             return 1;
    301.         }
    302.         conf.docroot = strdup(uh_buf); /* 结构体conf里的docroot字段保存了当前工作路径 */
    303.         /*
    304.         原型:extern char *strdup(char *s);
    305.         功能: 将字符串拷贝到新建的位置处
    306.         返回值:返回一个指针,指向为复制字符串分配的空间;如果分配空间失败,则返回NULL值
    307.         */
    308.         
    309.     }

    310.     init_defaults_post();
    311.     /* 初始化主页名和cgi的绝对路径 */

    312.     if (!bound) /* 如果没有绑定监听端口,则报错退出 */
    313.     {
    314.         fprintf(stderr, "Error: No sockets bound, unable to continue\n");
    315.         return 1;
    316.     }

    317. #ifdef HAVE_TLS /* 如果安装了tls,则执行 */
    318.     if (n_tls) /* 安装了tls,n_tls就不为0 */
    319.     {
    320.         if (!tls_crt || !tls_key) /* 没有公匙或者没有私匙,就报错并退出 */
    321.         {
    322.             fprintf(stderr, "Please specify a certificate and "
    323.                     "a key file to enable SSL support\n");
    324.             return 1;
    325.         }

    326.         if (uh_tls_init(tls_key, tls_crt)) /* 初始化tls,成功返回0 */
    327.             return 1;
    328.     }
    329. #endif

    330. #ifdef HAVE_LUA /* 如果安装了lua程序,则执行 */
    331.     if (conf.lua_handler || conf.lua_prefix) /* 两个变量其中一个有值就执行 */
    332.     {
    333.         /*
    334.         conf.lua_handler = optarg;    //file lua脚本文件
    335.         conf.lua_prefix = optarg;     //string 默认为'/lua'
    336.         */
    337.         if (!conf.lua_handler || !conf.lua_prefix) /* 两个变量其中一个没值就报错 */
    338.         {
    339.             fprintf(stderr, "Need handler and prefix to enable Lua support\n");
    340.             return 1;
    341.         }
    342.         
    343.         if (uh_plugin_init("uhttpd_lua.so")) /* 加载lua动态链接库 */
    344.             return 1;
    345.     }
    346. #endif

    347. #ifdef HAVE_UBUS /* 如果安装了ubus程序,则执行 */
    348.     /* 不是很理解这里,conf.ubus_prefix是否有值对结果不是很重要 */
    349.     if (conf.ubus_prefix && uh_plugin_init("uhttpd_ubus.so")) /* 插件初始化成功则会继续执行 */
    350.         return 1;        
    351. #endif

    352.     /* 程序如果还没有克隆自己,那现在开始克隆 */
    353.     if (!nofork) {
    354.    
    355.         switch (fork()) {
    356.         /*
    357.          在fork函数执行完毕后,如果创建新进程成功,则出现两个进程,一个是子进程,一个是父进程。
    358.          在子进程中,fork函数返回0,在父进程中,fork返回新创建子进程的进程ID。
    359.          我们可以通过fork返回的值来判断当前进程是子进程还是父进程。
    360.         */
    361.         
    362.         case -1: /* 如果出现错误,fork返回一个负值 */
    363.             perror("fork()"); /* 显示错误 */
    364.             /*
    365.             perror(s) 用来将上一个函数发生错误的原因输出到标准设备(stderr)。
    366.             参数 s 所指的字符串会先打印出,后面再加上错误原因字符串。
    367.             */
    368.             exit(1); /* 1是错误退出 */

    369.         case 0: /* 子进程执行这里,守护进程设置 */
    370.             
    371.             /* chdir 系统调用函数(同cd)
    372.                 原型: int chdir(const char *path );
    373.                 功 能:更改当前工作目录。
    374.                 参 数:Path 目标目录,可以是绝对目录或相对目录。
    375.                 返回值:成功返回0 ,失败返回-1
    376.             */
    377.             if (chdir("/")) /* 跳转成功不执行 */
    378.                 perror("chdir()"); /* 显示错误 */

    379.             /* open 系统调用函数
    380.                 原型:int open(constchar*pathname,intflags);
    381.                 参数1:pathname 是待打开/创建文件的POSIX路径名
    382.                 参数2:flags 用于指定文件的打开/创建模式
    383.                         O_RDONLY只读模式
    384.                         O_WRONLY只写模式
    385.                         O_RDWR读写模式
    386.                 返回值:成功则返回文件描述符,否则返回-1
    387.             */
    388.             cur_fd = open("/dev/null", O_WRONLY);
    389.             /* 由open返回的文件描述符一定是最小的未用描述符数值,打开的应该至少是文件描述符3 */
    390.             
    391.             if (cur_fd > 0) {
    392.             
    393.                 /*
    394.                 函数名: dup2
    395.                 功能: 复制文件句柄
    396.                 用法: int dup2(int oldfd,int newfd);
    397.                 */
    398.                
    399.                 dup2(cur_fd, 0);
    400.                 /* 功能是令文件描述符0 指向fd 所指向的文件,即“输入重定向”的功能 */
    401.                
    402.                 dup2(cur_fd, 1);
    403.                 /* 功能是令文件描述符1 指向fd 所指向的文件,即“输出重定向”的功能 */
    404.                
    405.                 dup2(cur_fd, 2);
    406.                 /* 功能是令文件描述符2 指向fd 所指向的文件,即“错误重定向”的功能 */
    407.             }
    408.             break;

    409.         default: /* 父进程执行这里 */
    410.             exit(0); /* 0是正常退出 */
    411.         }
    412.     }

    413.     return run_server();
    414. }
    复制代码
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2016-8-15 09:30
  • 签到天数: 162 天

    连续签到: 1 天

    [LV.7]常住居民III

     楼主| 发表于 2017-7-17 13:56:56 | 显示全部楼层
    主函数用到的函数:
    uh_config_parse
    1. /* uhttpd配置文件解析 */
    2. static void uh_config_parse(void)
    3. {
    4.     const char *path = conf.file;
    5.     /* config文件地址赋值给变量path */
    6.    
    7.     FILE *c;
    8.     /* 文件流对象c */
    9.    
    10.     char line[512];
    11.     /* 大小为512字节的数组 */
    12.    
    13.     char *col1;
    14.     /* 指向特定字符的指针,可以进行指针运算 */
    15.    
    16.     char *col2;
    17.     /* 指向特定字符的指针,可以进行指针运算 */
    18.    
    19.     char *eol;
    20.     /* 代表一个字符数组存储空间的首地址,可以进行指针运算 */

    21.     if (!path) /* 如果config文件地址没有定义,则赋默认值 */
    22.         path = "/etc/httpd.conf";

    23.     c = fopen(path, "r"); /* 打开config文件,只读模式,并将句柄赋给文件流对象c */
    24.    
    25.     if (!c) /* 如果句柄为空,则返回 */
    26.         return;

    27.     memset(line, 0, sizeof(line)); /* 用0填充line数组 */
    28.     /*
    29.     原型:void *memset(void *s, int ch, size_t n);
    30.     解释:将s中当前位置后面的n个字节用 ch 替换并返回 s
    31.     */

    32.     while (fgets(line, sizeof(line) - 1, c))
    33.     {
    34.         /* 从文件结构体指针stream中读取数据,每次读取一行。
    35.         原型:char *fgets(char *buf, int bufsize, FILE *stream);
    36.         参数1:*buf 字符型指针,指向用来存储所得数据的地址。
    37.         参数2:bufsize 整型数据,指明存储数据的大小。
    38.         参数3:*stream 文件结构体指针,将要读取的文件流。
    39.         返回值:成功,则返回第一个参数buf;失败NULL
    40.         */
    41.         
    42.         /* 查看了配置文件,好像下面判断里的代码都不会被执行 */
    43.         if ((line[0] == '/') && (strchr(line, ':') != NULL)) /* 行开头为'/',并且行里存在字符':',就执行下面 */
    44.         {
    45.             /*
    46.             原型:char *strchr(char* _Str,char _Ch)
    47.             功能:查找字符串_Str中首次出现字符_Ch的位置
    48.             返回值:成功则返回要查找字符第一次出现的位置,失败返回NUL
    49.             */
    50.         
    51.             /* 下面条件中只要有一个成立,就退出对line数组的操作 */
    52.             if (!(col1 = strchr(line, ':')) || /* ':'在line的首地址赋值给col1,然后取反,意思是存在就是变成0,不存在为1 */
    53.                 (*col1++ = 0) ||               /* 给col1地址赋0,然后col1指针加1 */
    54.                 !(col2 = strchr(col1, ':')) || /* ':'在line的第二地址赋值给col2,然后取反,意思是存在就是变成0,不存在为1 */
    55.                 (*col2++ = 0) ||               /* 给col2地址赋0,然后col2指针加1 */
    56.                 !(eol = strchr(col2, '\n')) || /* '\n'在line的地址赋值给eol,然后取反,意思是存在就是变成0,不存在为1 */
    57.                 (*eol++  = 0))                 /* 给eol地址赋0,然后eol指针加1 */
    58.                 continue;

    59.             uh_auth_add(line, col1, col2);
    60.             
    61.         }
    62.         else if (!strncmp(line, "I:", 2)) /* 行开头的两个字符为"I:",则执行下面 */
    63.         {
    64.             /*
    65.             原型:int strncmp ( const char * str1, const char * str2, size_t num );
    66.             功能:比较str1和str2字符串的前num个字符
    67.             返回值:若str1与str2的前n个字符相同,则返回0;
    68.                     若s1大于s2,则返回大于0的值;
    69.                     若s1 若小于s2,则返回小于0的值
    70.             */
    71.         
    72.             if (!(col1 = strchr(line, ':')) ||
    73.                 (*col1++ = 0) ||
    74.                 !(eol = strchr(col1, '\n')) ||
    75.                 (*eol++  = 0))
    76.                 continue;

    77.             uh_index_add(strdup(col1));
    78.             
    79.         }
    80.         else if (!strncmp(line, "E404:", 5)) /* 行开头的5个字符为"E404:",则执行下面 */
    81.         {
    82.             if (!(col1 = strchr(line, ':')) ||
    83.                 (*col1++ = 0) ||
    84.                 !(eol = strchr(col1, '\n')) ||
    85.                 (*eol++  = 0))
    86.                 continue;

    87.             conf.error_handler = strdup(col1);
    88.             
    89.         }
    90.         else if ((line[0] == '*') && (strchr(line, ':') != NULL)) /* 行开头为'*',并且行里存在字符':',就执行下面 */
    91.         {
    92.             if (!(col1 = strchr(line, '*')) ||
    93.                 (*col1++ = 0) ||
    94.                 !(col2 = strchr(col1, ':')) ||
    95.                 (*col2++ = 0) ||
    96.                 !(eol = strchr(col2, '\n')) ||
    97.                 (*eol++  = 0))
    98.                 continue;

    99.             uh_interpreter_add(col1, col2);
    100.             
    101.         }
    102.     }

    103.     fclose(c); /* 关闭文件流对象 */
    104. }
    复制代码
    init_defaults_post
    1. /* 初始化主页名和cgi的绝对路径 */
    2. static void init_defaults_post(void)
    3. {
    4.     /* 把默认主页名列表保存到链接表index_files */
    5.     uh_index_add("index.html");
    6.     uh_index_add("index.htm");
    7.     uh_index_add("default.html");
    8.     uh_index_add("default.htm");

    9.     /* 配置cgi的一些全局参数 */
    10.     if (conf.cgi_prefix)  /* option 'cgi_prefix' '/cgi-bin' */
    11.     {
    12.         char *str = malloc(strlen(conf.docroot) + strlen(conf.cgi_prefix) + 1);
    13.         /*
    14.             *str = malloc(strlen("/www/cgi_bin")+1)
    15.         */

    16.         strcpy(str, conf.docroot);
    17.         strcat(str, conf.cgi_prefix);
    18.         /*
    19.         原型:extern char *strcat(char *dest, const char *src);
    20.         功能:把src所指字符串添加到dest结尾处(覆盖dest结尾处的'\0')。
    21.         */
    22.         
    23.         conf.cgi_docroot_path = str; /* 配置文件的cgi_docroot_path指向cgi目录的绝对路径 */
    24.         conf.cgi_prefix_len = strlen(conf.cgi_prefix); /* '/cgi_bin'的长度为8 */
    25.     }
    26. }
    复制代码
    uh_index_add
    1. /* 本函数在file文件下 */
    2. void uh_index_add(const char *filename)
    3. {
    4.     struct index_file *idx;
    5.     /* index_file
    6.     struct list_head list;
    7.     const char *name;
    8.     */

    9.     idx = calloc(1, sizeof(*idx));
    10.     /*
    11.     原型:void *calloc(size_t n, size_t size);
    12.     功能:在内存的动态存储区中分配n个长度为size的连续空间
    13.     返回值:函数返回一个指向分配起始地址的指针;如果分配不成功,返回NULL。
    14.     */
    15.    
    16.     idx->name = filename;
    17.     list_add_tail(&idx->list, &index_files); /* index_files是一个全局结构体,双链接结构 */
    18.     /*
    19.     功能:把传进来的文件名保存到链接表
    20.     */
    21. }

    22. /* 为了代码逻辑清晰做的调整,一个待加入的链表值,一个前链表,一个链表头 */
    23. static inline void list_add_tail(struct list_head *_new, struct list_head *head)
    24. {
    25.     _list_add(_new, head->prev, head);
    26. }

    27. /* 向双向链表插入新的值 */
    28. static inline void _list_add(struct list_head *_new, struct list_head *prev, struct list_head *next)
    29. {
    30.     next->prev = _new;
    31.     _new->next = next;
    32.     _new->prev = prev;
    33.     prev->next = _new;
    34.     /*
    35.      ------          ------          ------
    36.     | next |        | next |        | next |
    37.     |------|        |------|        |------|
    38.     | prev |        | prev |        | prev |
    39.      ------          ------          ------
    40.       NEXT            NEW             PREV
    41.       
    42.   NEXT->prev -------> NEW
    43.       
    44.       NEXT  <------ NEW->next
    45.                     NEW->prev ------> PREV
    46.                     
    47.                       NEW <-------- PREV->next
    48.     */
    49. }
    复制代码
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2016-8-15 09:30
  • 签到天数: 162 天

    连续签到: 1 天

    [LV.7]常住居民III

     楼主| 发表于 2017-7-17 13:59:38 | 显示全部楼层
    haothree 发表于 2017-7-17 13:56
    uh_config_parseinit_defaults_postuh_index_add

    uh_tls_init
    1. /* 在uhttpd.c文件,功能是初始化安全传输层协议 */
    2. int uh_tls_init(const char *key, const char *crt)
    3. {
    4.     static bool _init = false;

    5.     if (_init)
    6.         return 0;

    7.     _init = true;
    8.     dlh = dlopen("libustream-ssl." LIB_EXT, RTLD_LAZY | RTLD_LOCAL);
    9.     /*
    10.     原型:void * dlopen( const char * pathname, int mode);
    11.     函数描述:mode是打开方式,其值有多个
    12.     功能:打开一个动态链接库,并返回动态链接库的句柄
    13.     LIB_EXT:不同的系统用不同的后缀,linux下是so,apple下是dylib
    14.     RTLD_LAZY(解析方式):在dlopen返回前,对于动态库中的未定义的符号不执行解析
    15.     RTLD_LOCAL(作用范围):动态库中定义的符号不能被其后打开的其它库重定位
    16.     */
    17.     if (!dlh) /* 如果动态链接库不存在,则报错并退出 */
    18.     {
    19.         fprintf(stderr, "Failed to load ustream-ssl library: %s\n", dlerror());
    20.         return -ENOENT;
    21.     }

    22.     ops = dlsym(dlh, "ustream_ssl_ops");
    23.     /*
    24.     原型:void * dlsym(void*handle,constchar*symbol)
    25.     功能:根据 动态链接库 操作句柄(handle)与符号(symbol),返回符号对应的地址。
    26.     */
    27.     if (!ops) /* 如果动态链接库地址不存在,则报错并退出 */
    28.     {
    29.         fprintf(stderr, "Could not find required symbol 'ustream_ssl_ops' in ustream-ssl library\n");
    30.         return -ENOENT;
    31.     }

    32.     ctx = ops->context_new(true);
    33.     /*
    34.     使用动态链接库的context_new函数创建一个新的对象
    35.     */
    36.     if (!ctx) /* 对象创建失败刚报错 */
    37.     {
    38.         fprintf(stderr, "Failed to initialize ustream-ssl\n");
    39.         return -EINVAL;
    40.     }

    41.     /* 加载公匙私匙失败,则报错 */
    42.     if (ops->context_set_crt_file(ctx, crt) || ops->context_set_key_file(ctx, key))
    43.     {
    44.         fprintf(stderr, "Failed to load certificate/key files\n");
    45.         return -EINVAL;
    46.     }

    47.     return 0;
    48. }
    复制代码
    uh_plugin_init
    1. /* plugin.c  插件初始化 */
    2. int uh_plugin_init(const char *name) /* name为插件文件名 */
    3. {
    4.     struct uhttpd_plugin *p; /* 动态链接库地址 */
    5.     const char *sym; /* 动态链接库符号 */
    6.     void *dlh; /* 动态链接库名柄 */

    7.     dlh = dlopen(name, RTLD_LAZY | RTLD_GLOBAL); /* 打开动态链接库 */
    8.     if (!dlh)  /* 无法打开动态链接库,报错退出 */
    9.     {
    10.         fprintf(stderr, "Could not open plugin %s: %s\n", name, dlerror());
    11.         return -ENOENT;
    12.     }

    13.     sym = "uhttpd_plugin";
    14.     p = dlsym(dlh, sym); /* 保存动态链接库地址 */
    15.     if (!p) /* 无法获得动态链接库地址,报错退出 */
    16.     {
    17.         fprintf(stderr, "Could not find symbol '%s' in plugin '%s'\n", sym, name);
    18.         return -ENOENT;
    19.     }

    20.     list_add(&p->list, &plugins); /* 把动态链接库保存到双链接表plugins */
    21.     return p->init(&ops, &conf); /* 初始化插件的配置内容 */
    22. }
    复制代码
    usage
    1. static int usage(const char *name)
    2. {
    3.     fprintf(stderr,
    4.         "Usage: %s -p [addr:]port -h docroot\n"
    5.         "    -f              Do not fork to background\n"
    6.         "    -c file         Configuration file, default is '/etc/httpd.conf'\n"
    7.         "    -p [addr:]port  Bind to specified address and port, multiple allowed\n"
    8. #ifdef HAVE_TLS
    9.         "    -s [addr:]port  Like -p but provide HTTPS on this port\n"
    10.         "    -C file         ASN.1 server certificate file\n"
    11.         "    -K file         ASN.1 server private key file\n"
    12.         "    -q              Redirect all HTTP requests to HTTPS\n"
    13. #endif
    14.         "    -h directory    Specify the document root, default is '.'\n"
    15.         "    -E string       Use given virtual URL as 404 error handler\n"
    16.         "    -I string       Use given filename as index for directories, multiple allowed\n"
    17.         "    -S              Do not follow symbolic links outside of the docroot\n"
    18.         "    -D              Do not allow directory listings, send 403 instead\n"
    19.         "    -R              Enable RFC1918 filter\n"
    20.         "    -n count        Maximum allowed number of concurrent script requests\n"
    21.         "    -N count        Maximum allowed number of concurrent connections\n"
    22. #ifdef HAVE_LUA
    23.         "    -l string       URL prefix for Lua handler, default is '/lua'\n"
    24.         "    -L file         Lua handler script, omit to disable Lua\n"
    25. #endif
    26. #ifdef HAVE_UBUS
    27.         "    -u string       URL prefix for UBUS via JSON-RPC handler\n"
    28.         "    -U file         Override ubus socket path\n"
    29.         "    -a              Do not authenticate JSON-RPC requests against UBUS session api\n"
    30.         "    -X        Enable CORS HTTP headers on JSON-RPC api\n"
    31. #endif
    32.         "    -x string       URL prefix for CGI handler, default is '/cgi-bin'\n"
    33.         "    -y alias[=path]    URL alias handle\n"
    34.         "    -i .ext=path    Use interpreter at path for files with the given extension\n"
    35.         "    -t seconds      CGI, Lua and UBUS script timeout in seconds, default is 60\n"
    36.         "    -T seconds      Network timeout in seconds, default is 30\n"
    37.         "    -k seconds      HTTP keepalive timeout\n"
    38.         "    -d string       URL decode given string\n"
    39.         "    -r string       Specify basic auth realm\n"
    40.         "    -m string       MD5 crypt given string\n"
    41.         "\n", name
    42.     );
    43.     return 1;
    44. }
    复制代码
    /*
    TLS: TLS(安全传输层协议)用于在两个通信应用程序之间提供保密性和数据完整性。
    LUA: LUA是一个小巧的脚本语言
    UBUS: UBUS是新openwrt引入的一个消息总线,主要作用是实现不同应用程序之间的信息交互
    */
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /2 下一条

    手机版|小黑屋|与非网

    GMT+8, 2024-4-18 19:17 , Processed in 0.137008 second(s), 18 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2020, Tencent Cloud.