#include <locale.h>
#include <libintl.h>
#define _(x) gettext(x)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __WIN32__
#include <winsock2.h>
#include <windows.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#endif
#include <errno.h>
#include "classicladder.h"
#include "global.h"
#include "protocol_modbus_slave.h"
#include "socket_server.h"
#include "protocol_modbus_master.h"
#ifdef __WIN32__
#define SOCK_FD SOCKET
#define SOCK_INVALID SOCKET_ERROR
HANDLE ThreadHandle = NULL;
DWORD ThreadId;
#else
#define SOCK_FD unsigned int
#define SOCK_INVALID -1
pthread_t thread_socket_server;
#endif
#define BUF_SIZE 512
SOCK_FD server_s; struct sockaddr_in server_addr;
int SocketOpened = 0;
int SocketRunning = 0;
void InitSocketServer( int UseUdpMode, int PortNbr )
{
int Error = 0;
#ifdef __WIN32__
WORD wVersionRequested = MAKEWORD(1,1); WSADATA wsaData; WSAStartup(wVersionRequested, &wsaData);
#else
signal(SIGPIPE, SIG_IGN);
#endif
if( ModbusDebugLevel>=2 ){ printf(_("INFO CLASSICLADDER--- INIT SOCKET!!!\n")); }
server_s = socket(AF_INET, SOCK_STREAM, 0);
if ( server_s==SOCK_INVALID )
{
printf(_("ERROR CLASSICLADDER--- Failed to open socket server...\n"));
}
else
{
SocketOpened = 1;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons( PortNbr );
server_addr.sin_addr.s_addr = htonl( INADDR_ANY );
Error = bind(server_s, (struct sockaddr *)&server_addr, sizeof(server_addr));
if ( Error==SOCK_INVALID )
{
printf(_("ERROR CLASSICLADDER--- Failed to bind socket server...(error=%s)\n"), strerror(errno));
CloseSocketServer( );
}
else
{
Error = listen(server_s, 1);
if ( Error==SOCK_INVALID )
{
printf(_("ERROR CLASSICLADDER--- Failed to listen socket server...(error=%s)\n"), strerror(errno));
CloseSocketServer( );
}
else
{
SocketRunning = 1;
#ifdef __WIN32__
ThreadHandle = CreateThread( NULL, 16*1024L,
(LPTHREAD_START_ROUTINE)SocketServerTcpMainLoop,
NULL,
THREAD_QUERY_INFORMATION,
&ThreadId);
if ( ThreadHandle==NULL )
#else
Error = pthread_create( &thread_socket_server, NULL, (void *(*)(void *))SocketServerTcpMainLoop, (void *)NULL );
if (Error)
#endif
{
printf(_("ERROR CLASSICLADDER--- Failed to create thread socket server...\n"));
CloseSocketServer( );
}
else
{ SocketRunning = 1;
printf(_("INFO CLASSICLADDER--- Server socket init ok (modbus - port %d)!\n"), PortNbr);
}
}
}
}
}
int AskAndAnswer( unsigned char * Ask, int LgtAsk, unsigned char * Answer )
{
int LgtModbusReply = 0;
int LgtHeaderReply = 0;
int i;
printf("-> ");
for (i=0; i<LgtAsk; i++)
{
if ( i==LGT_MODBUS_IP_HEADER )
printf("- ");
printf ("%02X ", Ask[i]);
}
printf("\n");
LgtModbusReply = ModbusRequestToRespond( &Ask[ LGT_MODBUS_IP_HEADER ], LgtAsk, &Answer[ LGT_MODBUS_IP_HEADER ] );
if ( LgtModbusReply>0 )
{
Answer[ LgtHeaderReply++ ] = Ask[ 0 ];
Answer[ LgtHeaderReply++ ] = Ask[ 1 ];
Answer[ LgtHeaderReply++ ] = 0;
Answer[ LgtHeaderReply++ ] = 0;
Answer[ LgtHeaderReply++ ] = (unsigned char)((LgtModbusReply+1)>>8);
Answer[ LgtHeaderReply++ ] = (unsigned char)(LgtModbusReply+1);
Answer[ LgtHeaderReply++ ] = 1;
printf(_("INFO CLASSICLADDER--- MODBUS RESPONSE LGT=%d+%d !\n"), LgtHeaderReply, LgtModbusReply );
printf("<- ");
for (i=0; i<LgtHeaderReply+LgtModbusReply; i++)
{
if ( i==LGT_MODBUS_IP_HEADER )
printf("- ");
printf ("%02X ", Answer[i]);
}
printf("\n");
}
return LgtHeaderReply+LgtModbusReply;
}
void SocketServerTcpMainLoop( void )
{
SOCK_FD client_s; struct sockaddr_in client_addr; unsigned int addr_len; unsigned char in_buf[BUF_SIZE]; unsigned char out_buf[BUF_SIZE];
int retcode;
#ifdef __XENO__
pthread_set_name_np(pthread_self(), __FUNCTION__);
#endif
while( SocketRunning )
{
if( ModbusDebugLevel>=2 ){ printf(_("INFO MODBUS SERVER--- SOCKET WAITING...\n")); }
addr_len = sizeof(client_addr);
client_s = accept(server_s, (struct sockaddr *)&client_addr, &addr_len);
if ( client_s!=-1 )
{
if( ModbusDebugLevel>=2 ){ printf(_("INFO MODBUS SERVER--- SOCKET CLIENT ACCEPTED...\n")); }
do
{
retcode = recv(client_s, in_buf, BUF_SIZE, 0);
if( ModbusDebugLevel>=2 ){ printf(_("INFO MODBUS SERVER--- SOCKET RECEIVED=%d !\n"), retcode); }
if ( retcode==-1 )
{
printf(_("ERROR CLASSICLADDER--- Failed to recv socket server...(error=%s)\n"), strerror(errno));
}
else
{
if ( retcode>0 )
{
int LgtReply = AskAndAnswer( in_buf, retcode, out_buf );
if ( LgtReply>0 )
send(client_s, out_buf, LgtReply, 0);
}
}
}
while( retcode>0 );
if( ModbusDebugLevel>=2 ){ printf(_("INFO MODBUS SERVER--- CLOSE SOCK CLIENT.\n")); }
#ifdef __WIN32__
closesocket(client_s);
#else
close(client_s);
#endif
}
}
#ifndef __WIN32__
pthread_exit(NULL);
#endif
}
void CloseSocketServer( void )
{
SocketRunning = 0;
#ifdef __WIN32__
if ( ThreadHandle )
TerminateThread( ThreadHandle, 0);
#endif
if ( SocketOpened )
{
#ifdef __WIN32__
closesocket(server_s);
WSACleanup();
#else
close(server_s);
#endif
SocketOpened = 0;
printf(_("INFO CLASSICLADDER--- Server socket closed!\n"));
}
}