HITDAQ/FPGA_nios/hit_pat/src/socket_server.c
2024-10-11 14:26:20 +02:00

333 lines
9.9 KiB
C

/******************************************************************************
* Copyright (c) 2006 Altera Corporation, San Jose, California, USA. *
* All rights reserved. All use of this software and documentation is *
* subject to the License Agreement located at the end of this file below. *
*******************************************************************************
* Date - October 24, 2006 *
* Module - simple_socket_server.c *
* *
******************************************************************************/
/******************************************************************************
* Simple Socket Server (SSS) example.
*
* This example demonstrates the use of MicroC/OS-II running on NIOS II.
* In addition it is to serve as a good starting point for designs using
* MicroC/OS-II and Altera NicheStack TCP/IP Stack - NIOS II Edition.
*
* -Known Issues
* None.
*
* Please refer to the Altera NicheStack Tutorial documentation for details on this
* software example, as well as details on how to configure the NicheStack TCP/IP
* networking stack and MicroC/OS-II Real-Time Operating System.
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
/* MicroC/OS-II definitions */
#include "includes.h"
/* Simple Socket Server definitions */
#include "socket_server.h"
//#include "alt_error_handler.h"
/* Nichestack definitions */
#include "ipport.h"
#include "tcpport.h"
#include "libport.h"
#include "osport.h"
static OS_EVENT *mutex;
static SSConn connections[NR_CHANNELS];
TK_OBJECT(to_sslistenertask);
TK_ENTRY(SSListenerTask);
struct inet_taskinfo sslistenertask =
{
&to_sslistenertask,
"socket server listener",
SSListenerTask,
SS_LISTENER_TASK_PRIORITY,
SS_LISTENER_STACK_SIZE,
};
// ********************************************************
void ss_reset_connection(SSConn* conn) //called e.g. after closing a socket
{
conn->fd_conn = -1;
conn->state = LISTENING;
return;
}
void ss_initialize_connection(SSConn* conn) //called only at initialization
{
conn->fd_conn = -1;
conn->fd_listen = -1;
conn->listenport = -1;
conn->state = FREE;
return;
}
void ss_handle_accept(SSConn* conn)
{
int socket;
int len;
struct sockaddr_in incoming_addr;
INT8U err;
OSMutexPend(mutex, 0, &err);
len = sizeof(incoming_addr);
//Close old connection if needed
if ((conn)->fd_conn != -1)
{
printf("[ss_handle_accept] closing old connection\n");
close(conn->fd_conn);
ss_reset_connection(conn);
}
if((socket=accept(conn->fd_listen,(struct sockaddr*)&incoming_addr,&len))<0)
{
//alt_NetworkErrorHandler(EXPANDED_DIAGNOSIS_CODE,
// "[ss_handle_accept] accept failed");
}
else
{
(conn)->fd_conn = socket;
(conn)->state = CONNECTED;
printf("[ss_handle_accept] accepted connection request from %s\n",
inet_ntoa(incoming_addr.sin_addr));
}
OSMutexPost(mutex);
return;
}
/*
* Listener Task()
*/
void SSListenerTask(void* param)
{
int max_socket = 0;
BSD_TIMEVAL_T timeout;
INT8U err;
OSMutexPend(mutex, 0, &err); //wrap initialization in a mutex - just in case...
timeout.tv_sec = 0;
timeout.tv_usec = 100000;
fd_set readfds; //set of descriptors
for (int ch = 0; ch < NR_CHANNELS; ch++)
if ((connections[ch].fd_listen = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
//printf("Errot initializing socket #%d!\n", ch);
//alt_NetworkErrorHandler(EXPANDED_DIAGNOSIS_CODE,"[sss_task] Socket creation failed");
}
//Binding etc. is done by ethernet_listen()
OSMutexPost(mutex);
//Now run in loop to handle incoming requests on all listening ports
while(1)
{
FD_ZERO(&readfds);
for (int ch = 0; ch < NR_CHANNELS; ch++)
if (connections[ch].listenport >= 0)
{
FD_SET(connections[ch].fd_listen, &readfds);
if (connections[ch].fd_listen >= max_socket)
max_socket = connections[ch].fd_listen+1;
}
if (max_socket == 0)
TK_SLEEP(10); //just sleep a bit if nothing to do
else
{
select(max_socket, &readfds, NULL, NULL, &timeout); //we must timeout from time to time to find newly set-up channels
for (int ch = 0; ch < NR_CHANNELS; ch++)
if (FD_ISSET(connections[ch].fd_listen, &readfds))
ss_handle_accept(&(connections[ch]));
}
} /* while(1) */
//never come here
}
// ****************** User interface ********************
int ethernet_init()
{
INT8U err;
mutex = OSMutexCreate(SS_LISTENER_TASK_PRIORITY-1, &err);
for (int ch = 0; ch < NR_CHANNELS; ch++)
ss_initialize_connection(&(connections[ch]));
TK_NEWTASK(&sslistenertask);
return 0;
}
int ethernet_listen(int channel, int port)
{
struct sockaddr_in addr;
INT8U err;
OSMutexPend(mutex, 0, &err);
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = INADDR_ANY;
if (bind(connections[channel].fd_listen,(struct sockaddr *)&addr,sizeof(addr)) < 0)
{
//alt_NetworkErrorHandler(EXPANDED_DIAGNOSIS_CODE,"[sss_task] Bind failed");
OSMutexPost(mutex);
return -1;
}
if (listen(connections[channel].fd_listen,1) < 0)
{
//alt_NetworkErrorHandler(EXPANDED_DIAGNOSIS_CODE,"[sss_task] Listen failed");
OSMutexPost(mutex);
return -2;
}
ss_reset_connection(&(connections[channel]));
connections[channel].listenport = port;
printf("[sss_task] Simple Socket Server listening on port %d\n", port);
OSMutexPost(mutex);
return 0;
}
int ethernet_write(int channel, int size, unsigned char* data)
{
int result;
INT8U err;
OSMutexPend(mutex, 0, &err);
if (connections[channel].fd_conn == -1) //socket is closed or channel unconfigured
{
OSMutexPost(mutex);
return 0;
}
result = (int)send(connections[channel].fd_conn, data, size, 0);
if (result == -1)
{
printf("[ethernet_write] closing connection due to error\n");
close(connections[channel].fd_conn); //close connection on error
ss_reset_connection(&(connections[channel]));
result = 0;
}
OSMutexPost(mutex);
return result;
}
int ethernet_read(int channel, int size, unsigned char* data)
{
fd_set readfds; //set of descriptors
int max_socket;
BSD_TIMEVAL_T timeout;
int result;
INT8U err;
OSMutexPend(mutex, 0, &err);
if (connections[channel].fd_conn == -1) //socket is closed or channel unconfigured
{
OSMutexPost(mutex);
return 0;
}
//prepare call parameters
FD_ZERO(&readfds);
FD_SET(connections[channel].fd_conn, &readfds);
max_socket = connections[channel].fd_conn+1;
timeout.tv_sec = 0;
timeout.tv_usec = 0;
//check for data
if (select(max_socket, &readfds, NULL, NULL, &timeout))
if (FD_ISSET(connections[channel].fd_conn, &readfds))
{
result = (int)recv(connections[channel].fd_conn, data, size, 0);
if (result == -1)
{
printf("[ethernet_read] closing connection due to error\n");
close(connections[channel].fd_conn); //close connection on error
ss_reset_connection(&(connections[channel]));
result = 0;
}
OSMutexPost(mutex);
return result;
}
OSMutexPost(mutex);
return 0;
}
int ethernet_close(int channel)
{
INT8U err;
OSMutexPend(mutex, 0, &err);
close(connections[channel].fd_conn);
ss_reset_connection(&(connections[channel]));
OSMutexPost(mutex);
return 0;
}
/******************************************************************************
* *
* License Agreement *
* *
* Copyright (c) 2009 Altera Corporation, San Jose, California, USA. *
* All rights reserved. *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
* DEALINGS IN THE SOFTWARE. *
* *
* This agreement shall be governed in all respects by the laws of the State *
* of California and by the laws of the United States of America. *
* Altera does not recommend, suggest or require that this reference design *
* file be used in conjunction or combination with any other product. *
******************************************************************************/