libuv学习笔记(21)

libuv学习笔记(21)

DNS相关功能

数据结构

typedef struct uv_getaddrinfo_s uv_getaddrinfo_t;
struct uv_getaddrinfo_s {
  UV_REQ_FIELDS//uv_req_t的成员
  uv_loop_t* loop;
  //UV_GETADDRINFO_PRIVATE_FIELDS展开:
  struct uv__work work_req;//线程池任务                                                  
  uv_getaddrinfo_cb getaddrinfo_cb;                                         
  void* alloc;//分配的内存的指针,方便释放                                                              
  WCHAR* node;                                                             
  WCHAR* service;                                                           
  struct addrinfoW* addrinfow;                                               
  struct addrinfo* addrinfo;//结果,需要通过uv_freeaddrinfo()释放                                           
  int retcode;
};
typedef struct uv_getnameinfo_s uv_getnameinfo_t;
struct uv_getnameinfo_s {
  UV_REQ_FIELDS//uv_req_t的成员
  uv_loop_t* loop;
  //UV_GETNAMEINFO_PRIVATE_FIELDS展开:
  struct uv__work work_req; //线程池任务                                                  
  uv_getnameinfo_cb getnameinfo_cb;                                           
  struct sockaddr_storage storage;//保存询问的地址                                           
  int flags;                                                                 
  char host[NI_MAXHOST];                                                 
  char service[NI_MAXSERV];                                                
  int retcode;
};

相关函数

`uv_getaddrinfo,获取地址信息
int uv_getaddrinfo(uv_loop_t* loop,
                   uv_getaddrinfo_t* req,
                   uv_getaddrinfo_cb getaddrinfo_cb,
                   const char* node,//主机名或ip地址
                   const char* service,//服务名或者端口
                   const struct addrinfo* hints) {
  int nodesize = 0;
  int servicesize = 0;
  int hintssize = 0;
  char* alloc_ptr = NULL;
  int err;
  if (req == NULL || (node == NULL && service == NULL)) {
    err = WSAEINVAL;
    goto error;
  }
  uv_req_init(loop, (uv_req_t*)req);//初始化请求
  req->getaddrinfo_cb = getaddrinfo_cb;
  req->addrinfo = NULL;
  req->type = UV_GETADDRINFO;
  req->loop = loop;
  req->retcode = 0;
  //获取node与service的长度
  //此处省略
  //
  if (hints != NULL) {
    hintssize = ALIGNED_SIZE(sizeof(struct addrinfoW));
  }
  //申请内存
  alloc_ptr = (char*)uv__malloc(nodesize + servicesize + hintssize);
  if (!alloc_ptr) {
    err = WSAENOBUFS;
    goto error;
  }
  req->alloc = (void*)alloc_ptr;
  //将node和service  utf8转换为unicode
  //都存储在alloc_ptr指向的内存中
  //此处省略
  //此处省略
  //将hints 的内容复制到req->addrinfow
  //此处省略

  uv__req_register(loop, req);
  if (getaddrinfo_cb) {//有回调函数,那么走loop流程
    uv__work_submit(loop,
                    &req->work_req,
                    uv__getaddrinfo_work,//调用GetAddrInfoW(req->node, req->service, hints, &req->addrinfow);
                    uv__getaddrinfo_done);//
    return 0;
  } else {//没有回调函数,直接调用
    uv__getaddrinfo_work(&req->work_req);
    uv__getaddrinfo_done(&req->work_req, 0);
    return req->retcode;
  }
error:
  if (req != NULL) {
    uv__free(req->alloc);
    req->alloc = NULL;
  }
  return uv_translate_sys_error(err);
}

获取信息之后loop调用的回调

static void uv__getaddrinfo_done(struct uv__work* w, int status) {
  uv_getaddrinfo_t* req;
  int addrinfo_len = 0;
  int name_len = 0;
  size_t addrinfo_struct_len = ALIGNED_SIZE(sizeof(struct addrinfo));
  struct addrinfoW* addrinfow_ptr;
  struct addrinfo* addrinfo_ptr;
  char* alloc_ptr = NULL;
  char* cur_ptr = NULL;
  req = container_of(w, uv_getaddrinfo_t, work_req);
  uv__free(req->alloc);//释放之前申请的内存
  req->alloc = NULL;
  if (status == UV_ECANCELED) {//被取消的请求
    assert(req->retcode == 0);
    req->retcode = UV_EAI_CANCELED;
    goto complete;
  }
  if (req->retcode == 0) {
    // 将addrinfoW转换为addrinfo
    //此处省略
    //将名字转换为utf8
    //此处省略
  //释放req->addrinfow
  if (req->addrinfow != NULL) {
    FreeAddrInfoW(req->addrinfow);
    req->addrinfow = NULL;
  }

complete:
  uv__req_unregister(req->loop, req);

  /* finally do callback with converted result */
  if (req->getaddrinfo_cb)//调用用户的回调函数
    req->getaddrinfo_cb(req, req->retcode, req->addrinfo);
}
释放地址内存
void uv_freeaddrinfo(struct addrinfo* ai) {
  char* alloc_ptr = (char*)ai;
  uv__free(alloc_ptr);
}
通过地址获取主机名
int uv_getnameinfo(uv_loop_t* loop,
                   uv_getnameinfo_t* req,
                   uv_getnameinfo_cb getnameinfo_cb,
                   const struct sockaddr* addr,//地址
                   int flags) {
  if (req == NULL || addr == NULL)
    return UV_EINVAL;
  if (addr->sa_family == AF_INET) {
    memcpy(&req->storage,
           addr,
           sizeof(struct sockaddr_in));
  } else if (addr->sa_family == AF_INET6) {
    memcpy(&req->storage,
           addr,
           sizeof(struct sockaddr_in6));
  } else {
    return UV_EINVAL;
  }

  uv_req_init(loop, (uv_req_t*)req);
  uv__req_register(loop, req);

  req->getnameinfo_cb = getnameinfo_cb;
  req->flags = flags;
  req->type = UV_GETNAMEINFO;
  req->loop = loop;
  req->retcode = 0;
  if (getnameinfo_cb) {
    uv__work_submit(loop,
                    &req->work_req,
                    uv__getnameinfo_work,//调用GetNameInfoW
                    uv__getnameinfo_done);
    return 0;
  } else {
    uv__getnameinfo_work(&req->work_req);
    uv__getnameinfo_done(&req->work_req, 0);
    return req->retcode;
  }
}

loop回调

static void uv__getnameinfo_done(struct uv__work* w, int status) {
  uv_getnameinfo_t* req;
  char* host;
  char* service;
  req = container_of(w, uv_getnameinfo_t, work_req);
  uv__req_unregister(req->loop, req);
  host = service = NULL;
  if (status == UV_ECANCELED) {
    assert(req->retcode == 0);
    req->retcode = UV_EAI_CANCELED;
  } else if (req->retcode == 0) {
    host = req->host;
    service = req->service;
  }
  if (req->getnameinfo_cb)//回调用户回调函数
    req->getnameinfo_cb(req, req->retcode, host, service);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值