技术标签: 网络 nginx nginx开发学习汇总 网络协议 ssl nginx反向代理
在ngx_http_init_connection中把recv→handler设置为ngx_http_ssl_handshake。
然后将这个读时间加入到epoll中,主要是分析handshake函数。
static void
ngx_http_ssl_handshake(ngx_event_t *rev)
{
...
n = recv(c->fd, (char *) buf, size, MSG_PEEK);
//判断协议
if (n == 1) {
if (buf[0] & 0x80 /* SSLv2 */ || buf[0] == 0x16 /* SSLv3/TLSv1 */) {
// 获取loc conf和server conf
clcf = ngx_http_get_module_loc_conf(hc->conf_ctx,
ngx_http_core_module);
if (clcf->tcp_nodelay && ngx_tcp_nodelay(c) != NGX_OK) {
ngx_http_close_connection(c);
return;
}
sscf = ngx_http_get_module_srv_conf(hc->conf_ctx,
ngx_http_ssl_module);
// 调用该函数生成ssl
if (ngx_ssl_create_connection(&sscf->ssl, c, NGX_SSL_BUFFER != NGX_OK)
{
ngx_http_close_connection(c);
return;
}
}
}
...
}
ngx_int_t
ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c, ngx_uint_t flags)
{
...
sc->session_ctx = ssl->ctx;
sc->connection = SSL_new(ssl->ctx);
if (sc->connection == NULL) {
ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_new() failed");
return NGX_ERROR;
}
if (SSL_set_fd(sc->connection, c->fd) == 0) {
ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_fd() failed");
return NGX_ERROR;
}
...
}
first收到client hello之后,完成初始化。
然后调用ngx_ssl_handshake函数,里面会调用openssl的ssl_do_handshake。
ngx_int_t
ngx_ssl_handshake(ngx_connection_t *c)
{
...
n = ngx_ssl_handshake_early_data(c);
n = SSL_do_handshake(c->ssl->connection);
...
}
do handshake的时候调用的是openssl的async job的库
int SSL_do_handshake(SSL *s)
{
...
if (SSL_in_init(s) || SSL_in_before(s)) {
if ((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) {
struct ssl_async_args args;
args.s = s;
ret = ssl_start_async_job(s, &args, ssl_do_handshake_intern);
} else {
ret = s->handshake_func(s);
}
}
...
}
int ASYNC_start_job(ASYNC_JOB **job, ASYNC_WAIT_CTX *wctx, int *ret,
int (*func)(void *), void *args, size_t size)
{
...
/* Start a new job */
if ((ctx->currjob = async_get_pool_job()) == NULL)
return ASYNC_NO_JOBS;
...
}
static ASYNC_JOB *async_get_pool_job(void) {
...
if (job == NULL) {
/* Pool is empty */
if ((pool->max_size != 0) && (pool->curr_size >= pool->max_size))
return NULL;
job = async_job_new();
if (job != NULL) {
if (! async_fibre_makecontext(&job->fibrectx)) {
async_job_free(job);
return NULL;
}
pool->curr_size++;
}
}
...
}
先get context做初始化,然后malloc一个stack,创建堆栈把函数放进去。
makecontext创建调用运行函数async_start_func,函数本身是使用当前job中的func。
int async_fibre_makecontext(async_fibre *fibre)
{
fibre->env_init = 0;
if (getcontext(&fibre->fibre) == 0) { //初始化当前ucontext
fibre->fibre.uc_stack.ss_sp = OPENSSL_malloc(STACKSIZE);
if (fibre->fibre.uc_stack.ss_sp != NULL) {
fibre->fibre.uc_stack.ss_size = STACKSIZE;
fibre->fibre.uc_link = NULL;
makecontext(&fibre->fibre, async_start_func, 0);
return 1;
}
} else {
fibre->fibre.uc_stack.ss_sp = NULL;
}
return 0;
}
pause job最关键的是swapcontext,在func中一旦被调用的话,就可以立即切换栈信息。
切回start_job的主函数,根据job→status=ASYNC_JOB_PAUSING来返回
int ASYNC_pause_job(void)
{
...
if (!async_fibre_swapcontext(&job->fibrectx,
&ctx->dispatcher, 1)) {
ASYNCerr(ASYNC_F_ASYNC_PAUSE_JOB, ASYNC_R_FAILED_TO_SWAP_CONTEXT);
return 0;
}
...
}
切回主函数后可以发现start job是for死循环任务,会根据job的状态进行返回
int ASYNC_start_job(ASYNC_JOB **job, ASYNC_WAIT_CTX *wctx, int *ret,
int (*func)(void *), void *args, size_t size)
{
...
for (;;) {
if (ctx->currjob != NULL) {
if (ctx->currjob->status == ASYNC_JOB_PAUSING) {
*job = ctx->currjob;
ctx->currjob->status = ASYNC_JOB_PAUSED;
ctx->currjob = NULL;
return ASYNC_PAUSE;
}
if (ctx->currjob->status == ASYNC_JOB_PAUSED) {
ctx->currjob = *job;
/* Resume previous job */
if (!async_fibre_swapcontext(&ctx->dispatcher,
&ctx->currjob->fibrectx, 1)) {
ASYNCerr(ASYNC_F_ASYNC_START_JOB,
ASYNC_R_FAILED_TO_SWAP_CONTEXT);
goto err;
}
continue;
}
...
}
static int ssl_start_async_job(SSL *s, struct ssl_async_args *args,
int (*func) (void *))
{
...
switch (ASYNC_start_job(&s->job, s->waitctx, &ret, func, args,
sizeof(struct ssl_async_args))) {
case ASYNC_ERR:
s->rwstate = SSL_NOTHING;
SSLerr(SSL_F_SSL_START_ASYNC_JOB, SSL_R_FAILED_TO_INIT_ASYNC);
return -1;
case ASYNC_PAUSE:
s->rwstate = SSL_ASYNC_PAUSED;
return -1;
}
...
}
返回的这个状态码,在nginx里面接到就是SSL_ERROR_WANT_ASYNC。
http://blog.sina.com.cn/s/blog_4b976b2d0100jk0b.html转载于:https://www.cnblogs.com/hengli/archive/2013/01/22/2870888.html_doxygen 类图包含组合关系
python + opencv 读取视频的三种情况:情况一:通过摄像头采集视频情况二:通过本地视频文件获取视频情况三:通过摄像头录制视频,再读取录制的视频摄像头采集、本地视频文件的读取、写视频文件,网上都有代码。我发现情况一和情况三都没有问题,大家注意读取自己通过摄像头录制的视频文件是没有问题的。但读取其他视频都会发现帧率为0(如果你获取视频的帧率并打印出来的话),并且
Swift字典(dictionary) 用来存储无序的相同类型数据的集合,Swift 字典会强制检测元素的类型,如果类型不同则会报错。每個值(value)都屬於一個唯一的鍵(key),鍵作為字典中這個值的識別符號,所有鍵的型別也必須相同(鍵與值的型別不一定要相同)。因為字典內的值沒有順序,所以需要根據這個鍵(key)來找到需要的值(value)。宣告字典型別時,使用Dictionary<Key, Value>這個方式,這裡的Key表示字典裡鍵的型別,Value表示字典裡儲存的型別,如下://_swift 字典
文章目录looploopAdditionalSlidesloopedSlidesloopFillGroupWithBlankloopPreventsSlideloop(1)loop模式:会在原本slide前后复制若干个slide(默认一个)并在合适的时候切换,让Swiper看起来是循环的。(2)注意:loop模式在与free模式同用时会产生抖动,因为free模式下没有复制slide的时间点。<div class="swiper-box"> <div class="s_swiper循环
今天在一个项目中添加jar包依赖后导入发现jar包下边出现红色波浪线,而且jar包的版本显示unknown,显示错误:Cannot resolve com.alibaba.spring:spring-context-support:unknown解决在maven的本地仓库中,将出现unknown的文件夹和后缀有lastUpdated的文件全部删掉,再重新导入jar包后就成功了..._未解析的依赖项: 'com.auth0:java-jwt:jar:unknown
ViewStub是Android中view的一种优化方案,它的目的是在不需要显示view的时候不去加载view,这样在view的创建时期,减少了加载的资源,优化了view。invisible 、gone 、 viewstub的区别:1、invisible view设置为invisible时,view在layout布局文件中会占用位置,但是view为不可见,该view还是会创建对象,会被初始......_viewbinding viewstub
-n参数的作用是抑制自动输出首先看下一文件data内容执行sed 's/dog/cat/p' data命令查看效果执行sed -n 's/dog/cat/p' data命令效果再看一组命令对比sed '2s/dog/cat/p' data和sed -n '2s/dog/cat/p' data命令运行效果如下:..._为什么sed s不能加 -n
在学习 Objective-C的过程中,感觉数组在这一个学习方面是一个比较大的应用域,所以写这篇随笔来总结一下。 首先声明的是,与C语言的数组不同,Objective-C的是数组只能用来存储对象,而不是存储int 、double、char等基础数据类型,一般要存这些基础数据类型,对于我这个刚学 Objective-C的新手来说,我的做法是将有关数字的基础类型 如 int 、do...
上一篇文章我们大致讲解了一下 HTTP 的基本特征和使用,大家反响很不错,那么本篇文章我们就来深究一下 HTTP 的特性。我们接着上篇文章没有说完的 HTTP 标头继续来介绍(此篇文章会介绍所有标头的概念,但没有深入底层)HTTP 标头先来回顾一下 HTTP1.1 标头都有哪几种HTTP 1.1 的标头主要分为四种,通用标头、实体标头、请求标头、响应标头,现在我们来对这几种标头进行介绍通用..._proxy-revalidate
***模型训练部分***原始特征+tfidf特征1.工具import pandas as pdimport numpy as npimport lightgbm as lgbmform lightgbm.sklearn import LGBMClassifierfrom sklearn.model_selection import GridSearchCVimport..._keyerror: 'multi_logloss-mean
报错详情在命令行中通过ssh命令连接服务器时出现了如下哗啦哗啦的报错,一行行的@让我有点不知所措。@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@IT IS POSSIBLE THAT SOMEONE IS _warning: remote host identification has changed! @ @@@@@@@@@@@@@@@@@@@@@@@@@
分享一个好玩的电脑技巧。制作精美的U盘,文夹夹图标,ICO格式,可以在线上传普通照片制作,如想要更多的图标,直接在baidu中查找下载了。在线制作网址:http://www.ico.la/下图是本人U盘的图标,有个性吧,本人电脑中硬盘的图标:制作方法:把autorun.inf文件和icon.ico文件放在所要制作的盘的..._u盘图标ico制作 -baijiahao