1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (c) 2022 Huawei Device Co., Ltd.
4 *
5 * Description: Demo example of NewIP udp server.
6 *
7 * Author: Yang Yanjun <yangyanjun@huawei.com>
8 *
9 * Data: 2022-09-06
10 */
11#include <stdio.h>
12#include <stdlib.h>
13#include <unistd.h>
14#include <string.h>
15#include <arpa/inet.h>
16#include <sys/types.h>
17#include <sys/socket.h>
18
19#define __USE_GNU
20#include <sched.h>
21#include <pthread.h>
22
23#include "nip_uapi.h"
24#include "nip_lib.h"
25#include "newip_route.h"
26
27void *recv_send(void *args)
28{
29	char buf[BUFLEN] = {0};
30	int fd, ret, recv_num;
31	int count = 0;
32	socklen_t slen;
33	struct sockaddr_nin si_remote;
34
35	memcpy(&fd, args, sizeof(int));
36	while (count < PKTCNT) {
37		slen = sizeof(si_remote);
38		memset(buf, 0, sizeof(char) * BUFLEN);
39		memset(&si_remote, 0, sizeof(si_remote));
40		recv_num = recvfrom(fd, buf, BUFLEN, 0, (struct sockaddr *)&si_remote, &slen);
41		if (recv_num < 0) {
42			printf("server recvfrom fail, ret=%d\n", ret);
43			goto END;
44		} else if (recv_num == 0) { /* no data */
45			;
46		} else {
47			printf("Received -- %s -- from 0x%x:%d\n", buf,
48			       si_remote.sin_addr.NIP_ADDR_FIELD16[0], ntohs(si_remote.sin_port));
49			slen = sizeof(si_remote);
50			ret = sendto(fd, buf, BUFLEN, 0, (struct sockaddr *)&si_remote, slen);
51			if (ret < 0) {
52				printf("server sendto fail, ret=%d\n", ret);
53				goto END;
54			}
55			printf("Sending  -- %s -- to 0x%0x:%d\n", buf,
56			       si_remote.sin_addr.NIP_ADDR_FIELD8[0], ntohs(si_remote.sin_port));
57		}
58		count++;
59	}
60END:	return NULL;
61}
62
63int main(int argc, char **argv)
64{
65	int fd;
66	pthread_t th;
67	struct sockaddr_nin si_local;
68
69	fd = socket(AF_NINET, SOCK_DGRAM, IPPROTO_UDP);
70	if (fd < 0) {
71		perror("socket");
72		return -1;
73	}
74
75	memset((char *)&si_local, 0, sizeof(si_local));
76	si_local.sin_family = AF_NINET;
77	si_local.sin_port = htons(UDP_SERVER_PORT);
78	// 2-byte address of the server: 0xDE00
79	si_local.sin_addr.NIP_ADDR_FIELD8[INDEX_0] = 0xDE;
80	si_local.sin_addr.NIP_ADDR_FIELD8[INDEX_1] = 0x00;
81	si_local.sin_addr.bitlen = NIP_ADDR_BIT_LEN_16; // 2-byte: 16bit
82
83	if (bind(fd, (const struct sockaddr *)&si_local, sizeof(si_local)) < 0) {
84		perror("bind");
85		goto END;
86	}
87
88	printf("bind success, addr=0x%02x%02x, port=%d\n",
89	       si_local.sin_addr.NIP_ADDR_FIELD8[INDEX_0],
90	       si_local.sin_addr.NIP_ADDR_FIELD8[INDEX_1], UDP_SERVER_PORT);
91
92	pthread_create(&th, NULL, recv_send, &fd);
93	/* Wait for the thread to end and synchronize operations between threads */
94	pthread_join(th, NULL);
95
96END:	close(fd);
97	return 0;
98}
99
100