13.6.2 向上游邮件服务器发起连接
根据ngx_mail_proxy_init方法可以启动Nginx与上游邮件服务器间的交互,下面看一下该方法主要做了哪些工作。
void ngx_mail_proxy_init(ngx_mail_session_ts,ngx_addr_tpeer)
{
……
//创建ngx_mail_proxy_ctx_t结构体
ngx_mail_proxy_ctx_t*p=ngx_pcalloc(s->connection->pool,sizeof(ngx_mail_proxy_ctx_t));
if(p==NULL){
ngx_mail_session_internal_server_error(s);
return;
}
//注意,之前的proxy成员指向的是NULL空指针
s->proxy=p;
……
//向上游的邮件服务器发起无阻塞的TCP连接
ngx_int_t rc=ngx_event_connect_peer(&p->upstream);
……
/需要监控接收邮件服务器的响应是否超时,于是把与上游间连接的读事件添加到定时器中/
ngx_add_timer(p->upstream.connection->read,cscf->timeout);
//设置连接的data成员指向ngx_mail_session_t结构体
p->upstream.connection->data=s;
/设置Nginx与客户端间连接读事件的回调方法为不会读取内容的ngx_mail_proxy_block_read方法,因为当前阶段Nginx不会与客户端交互/
s->connection->read->handler=ngx_mail_proxy_block_read;
/设置Nginx与上游间的连接写事件回调方法为什么事都不做的ngx_mail_proxy_dummy_handler方法,这意味着接下来向上游发送TCP流时,将不再通过epoll这个事件框架来调度,下一节将看到实际的用法/
p->upstream.connection->write->handler=ngx_mail_proxy_dummy_handler;
/建立Nginx与邮件服务器间的内存缓冲区,缓冲区大小由nginx.conf文件中的proxy_buffer配置项决定/
s->proxy->buffer=ngx_create_temp_buf(s->connection->pool,
pcf->buffer_size);
//注意,设置out为空,表示将不会再通过out向客户端发送响应
s->out.len=0;
//根据用户请求的协议设置实际的邮件认证方法
switch(s->protocol){
case NGX_MAIL_POP3_PROTOCOL:
//设置POP3协议进行邮件交互认证的方法
p->upstream.connection->read->handler=ngx_mail_proxy_pop3_handler;
s->mail_state=ngx_pop3_start;
break;
case NGX_MAIL_IMAP_PROTOCOL:
//设置IMAP进行邮件交互认证的方法
p->upstream.connection->read->handler=ngx_mail_proxy_imap_handler;
s->mail_state=ngx_imap_start;
break;
default:/NGX_MAIL_SMTP_PROTOCOL/
//设置SMTP进行邮件交互认证的方法
p->upstream.connection->read->handler=ngx_mail_proxy_smtp_handler;
s->mail_state=ngx_smtp_start;
break;
}
}
可以看到,其中最重要的工作在于分配了ngx_mail_proxy_ctx_t结构体,并为成员buffer分配了内存缓冲区,用于接收上游的TCP消息,同时使用upstream与上游建立了TCP连接,最后针对不同的邮件协议分别设置了ngx_mail_proxy_pop3_handler、ngx_mail_proxy_imap_handler或者ngx_mail_proxy_smtp_handler方法,用于Nginx与上游邮件服务器间的交互。