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与上游邮件服务器间的交互。