| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- #define DBG_ENABLE
- #define DBG_SECTION_NAME ("RyanW5500Ping")
- #define DBG_LEVEL LOG_LVL_INFO
- #define DBG_COLOR
- #include "RyanW5500Store.h"
- #define Sn_PROTO(ch) (0x001408 + (ch << 5))
- #define WIZ_PING_DATA_LEN 32
- #define WIZ_PING_HEAD_LEN 8
- #define WIZ_PING_PORT 3000
- #define WIZ_PING_REQUEST 8
- #define WIZ_PING_REPLY 0
- #define WIZ_PING_CODE 0
- #define WIZ_PING_DELAY (1000)
- #define WIZ_PING_TIMEOUT (2000)
- struct wiz_ping_msg
- {
- uint8_t type; // 0 - Ping Reply, 8 - Ping Request
- uint8_t code; // Always 0
- uint16_t check_sum; // Check sum
- uint16_t id; // Identification
- uint16_t seq_num; // Sequence Number
- int8_t data[WIZ_PING_DATA_LEN]; // Ping Data : 1452 = IP RAW MTU - sizeof(type+code+check_sum+id+seq_num)
- };
- /**
- * @brief 计算字符串校验值
- *
- * @param src
- * @param len
- * @return uint16_t
- */
- static uint16_t wiz_checksum(uint8_t *src, uint32_t len)
- {
- uint16_t sum, tsum, i, j;
- uint32_t lsum;
- j = len >> 1;
- lsum = 0;
- for (i = 0; i < j; i++)
- {
- tsum = src[i * 2];
- tsum = tsum << 8;
- tsum += src[i * 2 + 1];
- lsum += tsum;
- }
- if (len % 2)
- {
- tsum = src[i * 2];
- lsum += (tsum << 8);
- }
- sum = lsum;
- sum = ~(sum + (lsum >> 16));
- return (uint16_t)sum;
- }
- static int wiz_ping_request(int socket)
- {
- int idx, send_len;
- uint16_t tmp_checksum;
- struct wiz_ping_msg ping_req;
- // 设置请求ping消息对象
- ping_req.type = WIZ_PING_REQUEST;
- ping_req.code = WIZ_PING_CODE;
- ping_req.id = htons(rand() % 0xffff);
- ping_req.seq_num = htons(rand() % 0xffff);
- for (idx = 0; idx < WIZ_PING_DATA_LEN; idx++)
- ping_req.data[idx] = (idx) % 8;
- ping_req.check_sum = 0;
- // 计算请求ping消息校验值
- tmp_checksum = wiz_checksum((uint8_t *)&ping_req, sizeof(ping_req));
- ping_req.check_sum = htons(tmp_checksum);
- // 发送请求ping消息
- send_len = wiz_send(socket, &ping_req, sizeof(ping_req), 0);
- if (send_len != sizeof(ping_req))
- return -1;
- return send_len - WIZ_PING_HEAD_LEN;
- }
- static int wiz_ping_reply(int socket, struct sockaddr *from)
- {
- uint16_t tmp_checksum;
- uint8_t recv_buf[WIZ_PING_HEAD_LEN + WIZ_PING_DATA_LEN + 1];
- struct wiz_ping_msg ping_rep;
- int recv_len;
- int idx;
- platformTimer_t pingReplyTimer = {0};
- platformTimerCutdown(&pingReplyTimer, WIZ_PING_TIMEOUT);
- while (1)
- {
- if (0 == platformTimerRemain(&pingReplyTimer))
- return -1;
- struct sockaddr *sin = (struct sockaddr *)from;
- socklen_t addr_len = sizeof(struct sockaddr_in);
- recv_len = wiz_recvfrom(socket, recv_buf, WIZ_PING_HEAD_LEN + WIZ_PING_DATA_LEN, 0, sin, &addr_len);
- if (recv_len < 0)
- return -1;
- break;
- }
- switch (recv_buf[0])
- {
- case WIZ_PING_REPLY:
- ping_rep.type = recv_buf[0];
- ping_rep.code = recv_buf[1];
- ping_rep.check_sum = (recv_buf[3] << 8) + recv_buf[2];
- ping_rep.id = (recv_buf[5] << 8) + recv_buf[4];
- ping_rep.seq_num = (recv_buf[7] << 8) + recv_buf[6];
- for (idx = 0; idx < recv_len - 8; idx++)
- ping_rep.data[idx] = recv_buf[8 + idx];
- tmp_checksum = ~wiz_checksum(recv_buf, recv_len);
- if (tmp_checksum != 0xffff)
- return -2;
- break;
- case WIZ_PING_REQUEST:
- ping_rep.code = recv_buf[1];
- ping_rep.type = recv_buf[2];
- ping_rep.check_sum = (recv_buf[3] << 8) + recv_buf[2];
- ping_rep.id = (recv_buf[5] << 8) + recv_buf[4];
- ping_rep.seq_num = (recv_buf[7] << 8) + recv_buf[6];
- for (idx = 0; idx < recv_len - 8; idx++)
- ping_rep.data[idx] = recv_buf[8 + idx];
- tmp_checksum = ping_rep.check_sum;
- ping_rep.check_sum = 0;
- if (tmp_checksum != ping_rep.check_sum)
- return -2;
- break;
- default:
- LOG_W("unknown ping receive message.");
- return -1;
- }
- return recv_len - WIZ_PING_HEAD_LEN;
- }
- int RyanW5500Ping(struct netdev *netdev, const char *host, size_t data_len, uint32_t times, struct netdev_ping_resp *ping_resp)
- {
- int result = 0,
- socket = 0;
- struct hostent *hostent = NULL;
- hostent = wiz_gethostbyname(host);
- if (NULL == hostent || NULL == hostent->h_addr_list[0])
- {
- LOG_W("hostent is NULL.");
- return -RT_FALSE;
- }
- struct in_addr serviceAddr = *(struct in_addr *)hostent->h_addr_list[0];
- // SOCK_RAW == Sn_MR_IPRAW == 3
- socket = wiz_socket(AF_WIZ, SOCK_RAW, 0);
- if (socket < 0)
- {
- LOG_W("create ping socket(%d) failed.", socket);
- return -1;
- }
- // 设置套接字ICMP协议
- IINCHIP_WRITE(Sn_PROTO(socket), IPPROTO_ICMP);
- struct timeval timeout = {.tv_sec = times,
- .tv_usec = times % 1000 * 1000};
- // 设置接收和发送超时选项
- wiz_setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (void *)&timeout,
- sizeof(timeout));
- wiz_setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, (void *)&timeout,
- sizeof(timeout));
- struct sockaddr_in server_addr = {.sin_family = AF_WIZ,
- .sin_port = htons(WIZ_PING_PORT),
- .sin_addr = serviceAddr};
- if (wiz_connect(socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
- {
- wiz_closesocket(socket);
- return -1;
- }
- result = wiz_ping_request(socket);
- platformTimer_t pingTimer = {0};
- platformTimerCutdown(&pingTimer, 0xffff);
- if (result > 0)
- {
- result = wiz_ping_reply(socket, (struct sockaddr *)&server_addr);
- ping_resp->ip_addr.addr = serviceAddr.s_addr;
- ping_resp->ticks = 0xffff - platformTimerRemain(&pingTimer);
- ping_resp->data_len = data_len;
- wiz_getsockopt(socket, IPPROTO_IP, IP_TTL, &ping_resp->ttl, sizeof(ping_resp->ttl));
- }
- wiz_closesocket(socket);
- return result;
- }
|