网络协议栈接入方式

网络协议栈或网络功能实现的接入,主要是对协议簇结构体的初始化和注册处理,并且添加到 SAL 组件中协议簇列表中,协议簇结构体定义如下:

  1. struct proto_family
  2. {
  3. int family; /* primary protocol families type*/
  4. int sec_family; /* secondary protocol families type*/
  5. int (*create)(struct socket *socket, int type, int protocol); /* register socket options */
  6.  
  7. struct hostent* (*gethostbyname) (const char *name);
  8. int (*gethostbyname_r)(const char *name, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop);
  9. void (*freeaddrinfo) (struct addrinfo *ai);
  10. int (*getaddrinfo) (const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res);
  11. };
  • family: 每个协议栈支持的主协议簇类型,例如 lwIP 的为 AF_INET ,AT Socket 为 AF_AT。
  • sec_family:每个协议栈支持的次协议簇类型,用于支持单个协议栈或网络实现时,匹配软件包中其他类型的协议簇类型。
  • create: 主要是对 socket 相关执行函数的注册,例如 connect、close 等函数的,将当前协议栈的执行函数注册进创建的 SAL 组件中 socket 结构体中。
  • 其他函数: 为套接字无关执行函数,用于匹配每个协议栈或网络实现中的执行函数。
    以下为 AT Socket 网络实现的接入注册流程,开发者可参考实现其他的协议栈或网络实现的接入:
  1. #include <netdb.h>
  2. #include <sal.h> /* SAL 组件结构体存放头文件 */
  3. #include <at_socket.h> /* AT Socket 相关头文件 */
  4.  
  5. #ifdef RT_USING_DFS_NET
  6. #include <dfs_poll.h> /* poll 函数实现相关头文件 */
  7. #endif
  8.  
  9. #ifdef RT_USING_DFS_NET
  10. /* 自定义的 poll 执行函数,用于 poll 中处理接收的事件 */
  11. static int at_poll(struct dfs_fd *file, struct rt_pollreq *req)
  12. {
  13. int mask = 0;
  14. struct at_socket *sock;
  15. struct socket *sal_sock;
  16.  
  17. sal_sock = sal_get_socket((int) file->data);
  18. if(!sal_sock)
  19. {
  20. return -1;
  21. }
  22.  
  23. sock = at_get_socket((int)sal_sock->user_data);
  24. if (sock != NULL)
  25. {
  26. rt_base_t level;
  27.  
  28. rt_poll_add(&sock->wait_head, req);
  29.  
  30. level = rt_hw_interrupt_disable();
  31. if (sock->rcvevent)
  32. {
  33. mask |= POLLIN;
  34. }
  35. if (sock->sendevent)
  36. {
  37. mask |= POLLOUT;
  38. }
  39. if (sock->errevent)
  40. {
  41. mask |= POLLERR;
  42. }
  43. rt_hw_interrupt_enable(level);
  44. }
  45.  
  46. return mask;
  47. }
  48. #endif
  49.  
  50. /* 定义和赋值 Socket 执行函数,每个创建的新 Socket 套接字存在该执行函数存放与 Socket 结构体中,当执行相关函数是调用 */
  51. static const struct proto_ops at_inet_stream_ops =
  52. {
  53. at_socket,
  54. at_closesocket,
  55. at_bind,
  56. NULL,
  57. at_connect,
  58. NULL,
  59. at_sendto,
  60. at_recvfrom,
  61. at_getsockopt,
  62. at_setsockopt,
  63. at_shutdown,
  64. NULL,
  65. NULL,
  66. NULL,
  67.  
  68. #ifdef SAL_USING_POSIX
  69. at_poll,
  70. #else
  71. NULL,
  72. #endif /* SAL_USING_POSIX */
  73. };
  74.  
  75. static int at_create(struct socket *socket, int type, int protocol)
  76. {
  77. RT_ASSERT(socket);
  78. /* 协议簇结构体中 create 函数的实现,用于注册上面定义的 ops 执行函数到 socket 结构体中 */
  79. socket->ops = &at_inet_stream_ops;
  80. return 0;
  81. }
  82.  
  83. static const struct proto_family at_inet_family_ops = {
  84. AF_AT,
  85. AF_INET,
  86. at_create,
  87. /* Socket 套接字无关函数,由协议簇结构体注册 */
  88. at_gethostbyname,
  89. NULL,
  90. at_freeaddrinfo,
  91. at_getaddrinfo,
  92. };
  93.  
  94. int at_inet_init(void)
  95. {
  96. /* 注册协议簇结构体到协议簇列表,开发者通过 socket 函数传入的 family 类型匹配对应使用的协议簇类型 */
  97. sal_proto_family_register(&at_inet_family_ops);
  98. return 0;
  99. }
  100. /* 自动初始化函数 */
  101. INIT_COMPONENT_EXPORT(at_inet_init);