45 #define _________________________________________DEFINITIONS_SECTION________________________________________________________________________ 47 #define MODULE_NAME "Telnet" 49 #undef _________________________________________DEFINITIONS_SECTION________________________________________________________________________ 58 #define _________________________________________TYPES_SECTION______________________________________________________________________________ 90 oC_Timestamp_t InactiveTimestamp;
93 oC_MemorySize_t FilledSize;
140 Option_TimingMark = 6 ,
141 Option_TerminalType = 24 ,
142 Option_WindowSize = 31 ,
143 Option_TerminalSpeed = 32 ,
144 Option_RemoteFlowControl = 33 ,
145 Option_LineMode = 34 ,
146 Option_EnvironmentVariables = 36 ,
156 Operation_Will = 251 ,
157 Operation_Wont = 252 ,
159 Operation_Dont = 254 ,
174 #undef _________________________________________TYPES_SECTION______________________________________________________________________________ 181 #define _________________________________________PROTOTYPES_SECTION_________________________________________________________________________ 195 static oC_ErrorCode_t
Write (
ConnectionContext_t Context ,
const char * Buffer , uint32_t * Size , oC_Time_t Timeout );
196 static oC_ErrorCode_t
Read (
ConnectionContext_t Context ,
char * outBuffer , uint32_t * Size , oC_Time_t Timeout );
203 #undef _________________________________________PROTOTYPES_SECTION_________________________________________________________________________ 211 #define _________________________________________GLOBALS_SECTION____________________________________________________________________________ 219 .Name = MODULE_NAME ,
223 .MainThreadStackSize =
B(4096),
225 .AllocationLimit = 0 ,
226 .RequiredModules = { oC_Module_Tcp , oC_Module_ProcessMan , oC_Module_ThreadMan , oC_Module_NetifMan } ,
227 .Priority = oC_Process_Priority_NetworkHandlerProcess ,
235 .FileName = MODULE_NAME,
238 .Unconfigure = (oC_Driver_UnconfigureFunction_t)
Unconfigure ,
240 .Read = (oC_Driver_ReadFunction_t)
Read ,
243 #undef _________________________________________GLOBALS_SECTION____________________________________________________________________________ 252 #define _________________________________________FUNCTIONS_SECTION__________________________________________________________________________ 255 #undef _________________________________________FUNCTIONS_SECTION__________________________________________________________________________ 262 #define _________________________________________LOCAL_FUNCTIONS_SECTION____________________________________________________________________ 271 return isram(Context) &&
oC_CheckObjectControl(Context,oC_ObjectId_TelnetConnectionContext,Context->ObjectControl);
282 Allocator_t allocator = oC_Process_GetAllocator(Process);
284 if(oC_SaveIfFalse(
"context", context !=
NULL, oC_ErrorCode_AllocationError ))
286 context->Connection = Connection;
288 context->Stream =
NULL;
289 context->Process = Process;
290 context->Name = oC_Tcp_Connection_GetName(Connection);
293 context->NagleAlgorithm.Size = oC_DynamicConfig_GetValue(Telnet, NagleBufferSize);
294 context->NagleAlgorithm.Buffer = kmalloc( context->NagleAlgorithm.Size, allocator, AllocationFlags_ZeroFill );
295 context->NagleAlgorithm.FilledSize = 0;
296 context->NagleAlgorithm.Thread = oC_Thread_New(0, oC_DynamicConfig_GetValue(Telnet, NagleThreadStackSize), Process, context->Name,
NagleThread, context);
297 context->NagleAlgorithm.InactiveTimestamp = oC_DynamicConfig_GetValue(Telnet, NagleMaximumInactiveTime) + gettimestamp();
298 context->NagleAlgorithm.BusyMutex = oC_Mutex_New( oC_Mutex_Type_Normal, allocator, 0 );
299 context->NagleAlgorithm.CountingSemaphore = oC_Semaphore_New(context->NagleAlgorithm.Size,context->NagleAlgorithm.Size, allocator, 0 );
302 oC_SaveIfFalse(
"Thread", context->NagleAlgorithm.Thread !=
NULL , oC_ErrorCode_AllocationError )
303 && oC_SaveIfFalse(
"Size" , context->NagleAlgorithm.Size > 0 , oC_ErrorCode_SizeNotCorrect )
304 && oC_SaveIfFalse(
"Buffer", context->NagleAlgorithm.Buffer !=
NULL , oC_ErrorCode_AllocationError )
305 && oC_SaveIfFalse(
"Mutex" , context->NagleAlgorithm.BusyMutex !=
NULL , oC_ErrorCode_AllocationError )
306 && oC_SaveIfFalse(
"Semaph", context->NagleAlgorithm.CountingSemaphore !=
NULL , oC_ErrorCode_AllocationError )
307 && oC_SaveIfFalse(
"Thread", oC_Thread_Run(context->NagleAlgorithm.Thread) , oC_ErrorCode_CannotRunThread )
310 telnetlog( oC_LogType_Track,
"Connection context for '%s' has been allocated", context->Name );
314 telnetlog( oC_LogType_Error,
"Cannot allocate context for '%s'", context->Name );
316 oC_SaveIfFalse(
"thread" , oC_Thread_Delete(&context->NagleAlgorithm.Thread) , oC_ErrorCode_ReleaseError );
317 oC_SaveIfFalse(
"mutex" , oC_Mutex_Delete (&context->NagleAlgorithm.BusyMutex,0) , oC_ErrorCode_ReleaseError );
318 oC_SaveIfFalse(
"semaph" , oC_Semaphore_Delete(&context->NagleAlgorithm.CountingSemaphore,0), oC_ErrorCode_ReleaseError );
319 oC_SaveIfFalse(
"buffer" , kfree(context->NagleAlgorithm.Buffer,0) , oC_ErrorCode_ReleaseError );
320 oC_SaveIfFalse(
"context", kfree(context,0) , oC_ErrorCode_ReleaseError );
327 telnetlog( oC_LogType_Error,
"Cannot allocate memory for context");
340 bool deleted =
false;
342 oC_IntMan_EnterCriticalSection();
346 Context->ObjectControl = 0;
348 bool thread = oC_SaveIfFalse(
"thread" , oC_Thread_Delete(&Context->NagleAlgorithm.Thread) , oC_ErrorCode_ReleaseError );
349 bool mutex = oC_SaveIfFalse(
"mutex" , oC_Mutex_Delete (&Context->NagleAlgorithm.BusyMutex,0) , oC_ErrorCode_ReleaseError );
350 bool semaph = oC_SaveIfFalse(
"semaph" , oC_Semaphore_Delete(&Context->NagleAlgorithm.CountingSemaphore,0), oC_ErrorCode_ReleaseError );
351 bool buffer = oC_SaveIfFalse(
"buffer" , kfree(Context->NagleAlgorithm.Buffer,0) , oC_ErrorCode_ReleaseError );
352 bool context = oC_SaveIfFalse(
"context", kfree(Context,0) , oC_ErrorCode_ReleaseError );
354 deleted = thread && mutex && semaph && buffer && context;
357 oC_IntMan_ExitCriticalSection();
380 if(oC_SaveIfFalse(
"Telnet::ServiceContext_New: ", context !=
NULL, oC_ErrorCode_AllocationError ))
383 context->Server =
NULL;
396 bool deleted =
false;
400 bool serverDeleted = Context->Server ==
NULL ||
oC_Tcp_Server_Delete(&Context->Server, oC_DynamicConfig_GetValue(Telnet,StopServerTimeout));
404 deleted = free( Context, AllocationFlags_Default ) && serverDeleted;
417 oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
419 if(ErrorCondition( isram(outContext), oC_ErrorCode_OutputAddressNotInRAM ))
423 if(ErrorCondition( (*outContext) !=
NULL, oC_ErrorCode_AllocationError ))
425 errorCode = oC_ErrorCode_None;
439 oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
442 ErrorCondition( isram(Context) , oC_ErrorCode_AddressNotInRam )
449 errorCode = oC_ErrorCode_None;
463 oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
466 .Connection = Connection,
470 if(ErrorCondition( oC_Tcp_Connection_IsCorrect(Connection), oC_ErrorCode_ObjectNotCorrect ))
472 oC_Program_t program = oC_ProgramMan_GetDefaultProgram();
473 oC_Process_t process = oC_Program_NewProcess( program, getrootuser() );
475 const char * programName = oC_Program_GetName(program);
477 ErrorCondition( program !=
NULL && programName !=
NULL , oC_ErrorCode_ProgramNotCorrect )
478 && ErrorCondition( process !=
NULL , oC_ErrorCode_AllocationError )
481 config.Process = process;
483 stream = oC_Stream_New( oC_Process_GetAllocator(process),
484 AllocationFlags_Default,
485 oC_Stream_Type_Input | oC_Stream_Type_Output,
491 if( ErrorCondition( stream !=
NULL, oC_ErrorCode_AllocationError ) )
494 ErrorCode( oC_Process_SetOutputStream(process,stream) )
495 && ErrorCode( oC_Process_SetInputStream(process,stream) )
496 && ErrorCode( oC_Program_Exec(program,process,1,&programName,&thread) )
499 oC_SaveIfFalse(
"Cannot set Thread Finished Function",
501 oC_ErrorCode_ThreadNotCorrect );
502 errorCode = oC_ErrorCode_None;
504 if(oC_ErrorOccur(errorCode))
506 oC_SaveIfFalse(
"Telnet - cannot delete stream ", oC_Stream_Delete(&stream), oC_ErrorCode_ReleaseError );
509 if(oC_ErrorOccur(errorCode))
511 oC_SaveIfFalse(
"Telnet - cannot delete process ", oC_Process_Delete(&process), oC_ErrorCode_ReleaseError );
526 oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
527 bool serviceActive =
true;
529 uint32_t maxConnections = oC_DynamicConfig_GetValue( Telnet, MaxConnections );
530 oC_Time_t startTimeout = oC_DynamicConfig_GetValue( Telnet, StartServerTimeout );
540 && ErrorCode (
oC_Tcp_Listen( &source, &Context->Server, maxConnections, startTimeout ) )
543 kdebuglog( oC_LogType_Track,
"Telnet server has been started" );
552 kdebuglog( oC_LogType_Track,
"Telnet connection has been accepted" );
556 oC_SaveIfErrorOccur(
"Disconnecting after failure", oC_Tcp_Connection_Disconnect(connection, oC_DynamicConfig_GetValue(Telnet,DisconnectTimeout)));
561 serviceActive = errorCode == oC_ErrorCode_Timeout;
565 oC_SaveError(
"Telnet::ServiceThread: ", errorCode);
578 oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
583 oC_ARRAY_FOREACH_IN_ARRAY(options,option)
585 if(option->Command == Command_IAC)
587 if(option->Operation == Operation_Do)
589 if(option->Option == Option_Echo)
591 option->Operation = Operation_Will;
595 option->Operation = Operation_Wont;
598 else if(option->Operation == Operation_Will)
600 if(option->Option == Option_Echo)
602 option->Operation = Operation_Dont;
604 if(option->Option == Option_WindowSize)
606 option->Operation = Operation_Dont;
610 option->Operation = Operation_Do;
615 errorCode =
oC_Tcp_Send(Connection,options,
sizeof(options),
s(1));
617 else if(errorCode == oC_ErrorCode_Timeout)
619 errorCode = oC_ErrorCode_None;
632 oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
635 ErrorCondition( isaddresscorrect(Config) , oC_ErrorCode_WrongConfigAddress )
636 && ErrorCondition( isram(outContext) , oC_ErrorCode_OutputAddressNotInRAM )
637 && ErrorCondition( isram(outContext) , oC_ErrorCode_AddressNotInRam )
643 ErrorCondition( (*outContext) !=
NULL , oC_ErrorCode_AllocationError )
673 oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
674 oC_Time_t closingConnectionTimeout = oC_DynamicConfig_GetValue( Telnet, DisconnectTimeout );
678 && ErrorCode(
oC_Tcp_Disconnect( &((*Context)->Connection), closingConnectionTimeout ) )
679 && ErrorCondition( oC_Stream_Delete( &((*Context)->Stream)) ,oC_ErrorCode_ReleaseError )
683 errorCode = oC_ErrorCode_None;
696 oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
697 oC_Timestamp_t endTimestamp = gettimestamp() + Timeout;
701 && ErrorCondition( isaddresscorrect(Buffer) , oC_ErrorCode_WrongAddress )
702 && ErrorCondition( isram(Size) , oC_ErrorCode_AddressNotInRam )
703 && ErrorCondition( (*Size) > 0 , oC_ErrorCode_SizeNotCorrect )
704 && ErrorCondition( Timeout >= 0 , oC_ErrorCode_TimeNotCorrect )
707 if(gettimestamp() >= Context->NagleAlgorithm.InactiveTimestamp)
709 telnetlog(oC_LogType_Warning,
"%s: Nagle's thread seems to be inactive. Fflushing and sending data by our own", Context->Name);
712 ErrorCode(
Fflush(Context,gettimeout(endTimestamp)) )
713 && ErrorCode(
oC_Tcp_Send(Context->Connection, Buffer, *Size, gettimeout(endTimestamp)) )
716 errorCode = oC_ErrorCode_None;
723 errorCode = oC_ErrorCode_None;
727 oC_SaveError(
"Cannot save data in Nagle's Buffer", errorCode);
728 telnetlog( oC_LogType_Error,
"%s: Cannot save data in Nagle's buffer - %s, sending data without buffering", Context->Name,
oC_GetErrorString(errorCode) );
731 ErrorCode(
Fflush(Context,gettimeout(endTimestamp)) )
732 && ErrorCode(
oC_Tcp_Send(Context->Connection, Buffer, *Size, gettimeout(endTimestamp)) )
735 errorCode = oC_ErrorCode_None;
751 oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
754 && ErrorCondition( isram(outBuffer) , oC_ErrorCode_OutputAddressNotInRAM )
755 && ErrorCondition( (*Size) > 0 , oC_ErrorCode_SizeNotCorrect )
756 && ErrorCondition( Timeout >= 0 , oC_ErrorCode_TimeNotCorrect )
759 errorCode =
oC_Tcp_Receive(Context->Connection, outBuffer, *Size, Timeout);
774 telnetlog(oC_LogType_Track,
"TCP Connection has finished, killing process and unconfigure the stream");
777 oC_SaveIfFalse(
"Connection", oC_Tcp_Connection_IsCorrect(Connection), oC_ErrorCode_ObjectNotCorrect )
781 oC_SaveIfFalse(
"Process", oC_Process_Kill(context->Process), oC_ErrorCode_CannotKillProcess);
796 telnetlog(oC_LogType_Track,
"Main thread (%s) has finished", oC_Thread_GetName(Thread));
799 oC_SaveIfFalse(
"Thread" , oC_Thread_IsCorrect(Thread) , oC_ErrorCode_ObjectNotCorrect )
800 && oC_SaveIfFalse(
"Connection", oC_Tcp_Connection_IsCorrect(connection), oC_ErrorCode_ObjectNotCorrect )
803 if(oC_SaveIfFalse(
"Interrupts", oC_IntMan_AreInterruptsTurnedOn() , oC_ErrorCode_InterruptsNotEnabled))
805 static const char *
string =
"Closing connection with ChocoOS - the main thread has finished";
806 oC_Tcp_Connection_Send(Connection,
string,strlen(
string) + 1, oC_DynamicConfig_GetValue(Telnet,DisconnectTimeout));
808 oC_SaveIfErrorOccur(
"TCP disconnect", oC_Tcp_Connection_Disconnect(connection,oC_DynamicConfig_GetValue(Telnet,DisconnectTimeout)));
819 oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
820 oC_Timestamp_t endTimestamp = gettimestamp() + Timeout;
823 ErrorCondition( oC_Semaphore_TakeCounting(Context->NagleAlgorithm.CountingSemaphore, *Size, gettimeout(endTimestamp)), oC_ErrorCode_Timeout )
824 && ErrorCondition( oC_Mutex_Take(Context->NagleAlgorithm.BusyMutex, gettimeout(endTimestamp)) , oC_ErrorCode_Timeout )
827 uint8_t * buffer = &Context->NagleAlgorithm.Buffer[ Context->NagleAlgorithm.FilledSize ];
828 oC_MemorySize_t leftSize = Context->NagleAlgorithm.Size - Context->NagleAlgorithm.FilledSize;
829 oC_MemorySize_t sizeToCopy = oC_MIN(leftSize,*Size);
831 memcpy( buffer, Data, sizeToCopy );
833 Context->NagleAlgorithm.FilledSize += sizeToCopy;
835 errorCode = oC_ErrorCode_None;
837 oC_Mutex_Give(Context->NagleAlgorithm.BusyMutex);
850 oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
851 oC_Timestamp_t endTimestamp = gettimestamp() + Timeout;
853 if( ErrorCondition( oC_Mutex_Take(Context->NagleAlgorithm.BusyMutex, gettimeout(endTimestamp)) , oC_ErrorCode_Timeout ) )
855 if(Context->NagleAlgorithm.FilledSize > 0)
857 if( ErrorCode(
oC_Tcp_Send(Context->Connection, Context->NagleAlgorithm.Buffer, Context->NagleAlgorithm.FilledSize, gettimeout(endTimestamp)) ) )
859 errorCode = oC_ErrorCode_None;
864 errorCode = oC_ErrorCode_None;
867 memset(Context->NagleAlgorithm.Buffer, 0, Context->NagleAlgorithm.Size);
868 Context->NagleAlgorithm.FilledSize = 0;
869 oC_Mutex_Give(Context->NagleAlgorithm.BusyMutex);
870 oC_Semaphore_GiveCounting(Context->NagleAlgorithm.CountingSemaphore, Context->NagleAlgorithm.Size);
883 oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
885 telnetlog( oC_LogType_Track,
"Telnet Nagle's thread has been started" );
891 while(oC_Tcp_Connection_IsConnected(context->Connection))
893 context->NagleAlgorithm.InactiveTimestamp = oC_DynamicConfig_GetValue(Telnet, NagleMaximumInactiveTime) + gettimestamp();
895 errorCode =
Fflush(context,oC_DynamicConfig_GetValue(Telnet,NagleSendingTimeout));
897 if(errorCode == oC_ErrorCode_Timeout)
899 telnetlog( oC_LogType_Warning,
"%s: Cannot fflush data, mutex busy", context->Name);
901 else if(!oC_SaveIfErrorOccur(
"Fflush", errorCode ))
903 telnetlog( oC_LogType_Error,
"%s: Cannot fflush data. Error - %s", context->Name,
oC_GetErrorString(errorCode));
906 sleep(oC_DynamicConfig_GetValue(Telnet,NaglePeriod));
910 telnetlog( oC_LogType_Track,
"Telnet Nagle's thread has been finished" );
913 #undef _________________________________________LOCAL_FUNCTIONS_SECTION____________________________________________________________________ static oC_ErrorCode_t StartService(ServiceContext_t *outContext)
prepares Telnet service to work
static bool ServiceContext_Delete(ServiceContext_t Context)
releases memory of a service context
#define s(time)
Number of s.
The file with interface for programs.
static bool IsConnectionContextCorrect(ConnectionContext_t Context)
checks if the telnet connection context is correct
File with interface for TELNET protocol.
static void MainThreadFinished(oC_Thread_t Thread, void *Connection)
function called when the main thread is finished
static oC_ErrorCode_t Configure(VirtualDriverConfig_t *Config, ConnectionContext_t *outContext)
configures TELNET connection to work
stores TCP connection data
Operation_t
stores operation codes
The file with interface for thread managing.
static oC_ErrorCode_t RunProgramForConnection(oC_Tcp_Connection_t Connection, oC_Tcp_Server_t Server)
runs default program for specific TCP connection
identifier for allocations
static void NagleThread(void *Context)
thread for handling Nagle's buffering
oC_ErrorCode_t oC_Tcp_Disconnect(oC_Tcp_Connection_t *Connection, oC_Time_t Timeout)
disconnects TCP connection
static const oC_Driver_Registration_t DriverRegistration
registration of the Telnet dummy driver
static ConnectionContext_t ConnectionContext_New(oC_Tcp_Connection_t Connection, oC_Process_t Process)
allocates memory for the telnet connection context
#define B(Bytes)
Number of bytes.
#define ms(time)
Number of ms.
static oC_ErrorCode_t EstablishTelnetConnection(oC_Tcp_Connection_t Connection)
function for establishing telnet connection
Transmission Control Protocol.
struct Tcp_Connection_t * oC_Tcp_Connection_t
stores TCP connection data
static oC_ErrorCode_t SaveDataInNagleBuffer(ConnectionContext_t Context, const char *Data, uint32_t *Size, oC_Time_t Timeout)
saves data in Nagle's Buffer
static void ConnectionFinished(oC_Tcp_Connection_t Connection, void *Context)
function called when the connection has been finished
oC_ErrorCode_t oC_Tcp_Accept(oC_Tcp_Server_t Server, oC_Tcp_Connection_t *outConnection, oC_Time_t Timeout)
waits for new connection and accepts it
Telnet protocol—unencrypted text communications.
static oC_ErrorCode_t Fflush(ConnectionContext_t Context, oC_Time_t Timeout)
flushes data from Nagle's buffer
uint32_t oC_ObjectControl_t
stores object control value
static bool ServiceContext_IsCorrect(ServiceContext_t Context)
checks if the telnet context is correct
The file with list library.
static oC_ErrorCode_t Write(ConnectionContext_t Context, const char *Buffer, uint32_t *Size, oC_Time_t Timeout)
function called when process want to write data on STDOUT stream
The file with interface for interrupt manager.
Option_t
stores options of the telnet
Handles configuration of the Dynamic.
const oC_Service_Registration_t Telnet
registration of the Telnet service
configuration for a virtual driver
static oC_ObjectControl_t oC_CountObjectControl(void *ObjectPointer, oC_ObjectId_t ObjectId)
counts object control for object
static bool oC_CheckObjectControl(void *ObjectPointer, oC_ObjectId_t ObjectId, oC_ObjectControl_t ObjectControl)
checks if object control is correct
static ServiceContext_t ServiceContext_New(void)
allocates memory for a service context
The file with interface for mutex managing.
static bool ConnectionContext_Delete(ConnectionContext_t Context)
releases memory of the telnet connection context
static oC_ErrorCode_t Read(ConnectionContext_t Context, char *outBuffer, uint32_t *Size, oC_Time_t Timeout)
function called when process want to read data from STDIN stream
oC_ObjectControl_t ObjectControl
The file with interface for program manager.
oC_ErrorCode_t oC_Tcp_Send(oC_Tcp_Connection_t Connection, const void *Buffer, oC_MemorySize_t Size, oC_Time_t Timeout)
sends data by using TCP connection
static oC_ErrorCode_t Unconfigure(void *Dummy, ConnectionContext_t *Context)
unconfigures virtual telnet driver
The file with interface for process mechanism.
Command_t
stores commands for Telnet
interface for handling services
oC_ErrorCode_t oC_Tcp_Listen(const oC_Net_Address_t *Source, oC_Tcp_Server_t *outServer, uint32_t MaxConnections, oC_Time_t Timeout)
starts a server that listen at the given address
const char * oC_GetErrorString(oC_ErrorCode_t ErrorCode)
stores Telnet option data
The file with interface for semaphores.
static oC_ErrorCode_t ServiceThread(ServiceContext_t Context)
main Telnet service thread
oC_ErrorCode_t oC_Tcp_Server_SetConnectionFinished(oC_Tcp_Server_t Server, oC_Tcp_ConnectionFinishedFunction_t Function, void *Parameter)
sets a pointer for 'connection finished function'
oC_ErrorCode_t oC_Tcp_Receive(oC_Tcp_Connection_t Connection, void *outBuffer, oC_MemorySize_t Size, oC_Time_t Timeout)
receives data by using TCP connection
#define day(time)
Number of day.
context of the Telnet connection
static oC_ErrorCode_t StopService(ServiceContext_t *Context)
releases Telnet service resources
struct ConnectionContext_t * ConnectionContext_t
context of the Telnet connection
struct Context_t * ServiceContext_t
context of the Telnet Service
oC_Net_Port_t Port
Port of the address.
bool oC_Tcp_Server_Delete(oC_Tcp_Server_t *Server, oC_Time_t Timeout)
deletes TCP server
#define NULL
pointer to a zero