/*
 * tcp_svr_test.c
 *
 * created: 2023-01-17
 *  author: 
 */

/*
 * RTEMS Task for tcp_server_task, Auto Generated by Wizard.
 * Created: 2023-01-17 12:28:00
 */

#include "udp_tcp_test.h"

#if TCP_TSET

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>

#include <rtems.h>
#include <rtems/error.h>

#include <bsp.h>

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

//-----------------------------------------------------------------------------

static char local_IP[]  = "192.168.1.123";
//static char remote_IP[] = "192.168.1.111";

static char msg[64] = "hello, I'm tcp server!\n";

#define TCP_LOCAL_PORT      9060    // 本地端口
#define TCP_REMOTE_PORT     9061    // 远程端口

//-----------------------------------------------------------------------------

static rtems_id tcp_server_task_taskid;

static rtems_task tcp_server_task_task(rtems_task_argument arg)
{
    /*
     * Add tcp_server_task initialize code here.
     */
	struct sockaddr_in local_addr;
	int svr_fd, err;

	svr_fd = socket(AF_INET, SOCK_STREAM, 6);
	if (svr_fd < 0)
    {
		printf("failed to create sock_fd!\n");
		return;
	}

	memset(&local_addr, 0, sizeof(local_addr));
	local_addr.sin_family = AF_INET;
	local_addr.sin_addr.s_addr = inet_addr(local_IP);       // 192.168.1.123:9060
	local_addr.sin_port = htons(TCP_LOCAL_PORT);
    local_addr.sin_len = sizeof(local_addr);

	err = bind(svr_fd, (struct sockaddr *)&local_addr, sizeof(struct sockaddr));
	if (err < 0)
	{
	    close(svr_fd); // closesocket(svr_fd);
	    printf("failed to bind()!\n");
		return;
	}

    err = listen(svr_fd, 3);
	if (err < 0)
	{
	    close(svr_fd); // closesocket(svr_fd);
	    printf("failed to listen()!\n");
		return;
	}

    for ( ; ; )
    {
        /*
         * Add tcp_server_task task code here.
         */
        int client_fd;
        struct sockaddr_in client_addr;
        socklen_t addrlen = sizeof(struct sockaddr_in);

        client_fd = accept(svr_fd, &client_addr, &addrlen);
        
        if (client_fd > 0)
        {
            printf("%s", "client incoming...\r\n");

            /*
             * loop second.
             */
            for (;;)
            {
                memset(msg, 0, 64);
                err = recv(client_fd, msg, sizeof(msg), 0);

                if (err > 0)
                {
                    printf("SERVER REPLAY: %s", msg);
                    send(client_fd, msg, err, 0);
                }

				else if (err == -12 /*ERR_CLSD */)           /* 断开连接 */
				{
					close(client_fd);
					printf("%s", "client disconnected.\r\n");
					break;
				}

				else if (err <= 0)                  /* Error */
				{
				    close(client_fd);
				    printf("%s", "disconnect client...\r\n");
				    break;
				}

				rtems_task_wake_after(1);
            }
        }

        // ...

        /* abandon cpu time to run other task */
        rtems_task_wake_after(10);                      // task sleep 10 ms
        //rtems_task_wake_after(RTEMS_YIELD_PROCESSOR); // task sleep until cpu idle
        //rtems_task_wake_when(When);                   // task sleep to time When

    }
}

int tcp_server_task_create(void)
{
    rtems_status_code rc;

    /* create the task */
    rc = rtems_task_create(rtems_build_name('T', 'C', 'P', 's'),
                           100,             // TODO PRIORITY
                           (8*1024),        // TODO Stack Size
                           RTEMS_DEFAULT_MODES,
                           RTEMS_DEFAULT_ATTRIBUTES,
                           &tcp_server_task_taskid);

    if (RTEMS_SUCCESSFUL == rc)
    {
        /* start the task */
        rc = rtems_task_start(tcp_server_task_taskid, tcp_server_task_task, 0);
        if (RTEMS_SUCCESSFUL != rc)
        {
            /* start fail, clear the task */
            rtems_task_delete(tcp_server_task_taskid);
        }
        printf("start task tcp_server_task %s\r\n", rtems_status_text(rc));
    }
    else
        printf("create task tcp_server_task %s\r\n", rtems_status_text(rc));

    return rc;
}

#endif // #if TCP_TSET

