Choco OS  V.0.16.9.0
Join to the chocolate world
oc_udp.c
Go to the documentation of this file.
1 
27 #include <oc_udp.h>
28 #include <oc_intman.h>
29 #include <oc_list.h>
30 #include <oc_event.h>
31 #include <oc_mutex.h>
32 #include <oc_module.h>
33 #include <oc_processman.h>
34 #include <oc_memman.h>
35 #include <oc_netifman.h>
36 
42 #define _________________________________________TYPES_SECTION______________________________________________________________________________
43 
44 typedef struct
45 {
46  oC_Udp_Port_t Port;
47  oC_Process_t Process;
48  oC_Mutex_t Busy;
50 
51 typedef struct
52 {
53  oC_Udp_Packet_t* Packet;
54  oC_Netif_t Netif;
56 
57 typedef enum
58 {
59  PortPurpose_Source ,
60  PortPurpose_Destination
61 } PortPurpose_t;
62 
63 typedef struct
64 {
65  oC_Udp_Port_t DestinationPort;
66  oC_Netif_t ExpectedNetif;
68 
69 #undef _________________________________________TYPES_SECTION______________________________________________________________________________
70 
76 #define _________________________________________PROTOTYPES_SECTION_________________________________________________________________________
77 
78 static bool PacketFilterFunction ( oC_Net_Packet_t * Packet , const void * Parameter , oC_Netif_t Netif );
80 static uint16_t CalculateChecksum ( oC_Udp_Packet_t * Packet );
81 static bool IsSpecialPort ( oC_Udp_Port_t Port );
82 static bool IsPortReserved ( oC_Udp_Port_t Port );
83 static void ConvertHeaderToNetworkEndianess ( oC_Udp_Header_t * Header );
84 static void ConvertHeaderFromNetworkEndianess ( oC_Udp_Header_t * Header );
85 
86 #undef _________________________________________PROTOTYPES_SECTION_________________________________________________________________________
87 
93 #define _________________________________________VARIABLES_SECTION__________________________________________________________________________
94 
95 static oC_List(ReservationData_t*) ReservedPorts = NULL;
96 static oC_Event_t PortReleased = NULL;
97 static oC_Mutex_t ModuleBusy = NULL;
98 static const oC_Allocator_t Allocator = { .Name = "UDP" };
99 
100 #undef _________________________________________VARIABLES_SECTION__________________________________________________________________________
101 
102 
108 #define _________________________________________FUNCTIONS_SECTION_________________________________________________________________________
109 
114 //==========================================================================================================================================
131 //==========================================================================================================================================
132 oC_ErrorCode_t oC_Udp_TurnOn( void )
133 {
134  oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
135 
136  oC_IntMan_EnterCriticalSection();
137  if(
138  oC_Module_TurnOffVerification(&errorCode, oC_Module_Udp)
139  )
140  {
141  ReservedPorts = oC_List_New(&Allocator, AllocationFlags_Default);
142  PortReleased = oC_Event_New( oC_Event_State_Inactive, &Allocator, AllocationFlags_Default );
143  ModuleBusy = oC_Mutex_New( oC_Mutex_Type_Normal , &Allocator, AllocationFlags_Default);
144 
145  if(
146  ErrorCondition( ReservedPorts != NULL , oC_ErrorCode_AllocationError )
147  && ErrorCondition( ModuleBusy != NULL , oC_ErrorCode_AllocationError )
148  && ErrorCondition( PortReleased != NULL , oC_ErrorCode_AllocationError )
149  )
150  {
151  oC_Module_TurnOn(oC_Module_Udp);
152  errorCode = oC_ErrorCode_None;
153  }
154  else
155  {
156  bool listDeleted = oC_List_Delete( ReservedPorts , AllocationFlags_Default);
157  bool mutexDeleted = oC_Mutex_Delete(&ModuleBusy , AllocationFlags_Default);
158  bool eventDeleted = oC_Event_Delete(&PortReleased , AllocationFlags_Default);
159 
160  oC_SaveIfFalse("UDP:TurnOn - Cannot delete list " , listDeleted , oC_ErrorCode_ReleaseError );
161  oC_SaveIfFalse("UDP:TurnOn - Cannot delete mutex " , mutexDeleted , oC_ErrorCode_ReleaseError );
162  oC_SaveIfFalse("UDP:TurnOn - Cannot delete event " , eventDeleted , oC_ErrorCode_ReleaseError );
163  }
164  }
165  oC_IntMan_ExitCriticalSection();
166 
167  return errorCode;
168 }
169 
170 //==========================================================================================================================================
187 //==========================================================================================================================================
188 oC_ErrorCode_t oC_Udp_TurnOff( void )
189 {
190  oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
191 
192  oC_IntMan_EnterCriticalSection();
193  if(
194  oC_Module_TurnOnVerification(&errorCode , oC_Module_Udp)
195  )
196  {
197  oC_Module_TurnOff(oC_Module_Udp);
198 
199  bool allPacketsReleased = true;
200 
201  bool listDeleted = oC_List_Delete ( ReservedPorts , AllocationFlags_Default );
202  bool eventDeleted = oC_Event_Delete( &PortReleased , AllocationFlags_Default );
203  bool mutexDeleted = oC_Mutex_Delete( &ModuleBusy , AllocationFlags_Default );
204 
205  if(
206  ErrorCondition( listDeleted , oC_ErrorCode_ReleaseError )
207  && ErrorCondition( allPacketsReleased , oC_ErrorCode_ReleaseError )
208  && ErrorCondition( eventDeleted , oC_ErrorCode_ReleaseError )
209  && ErrorCondition( mutexDeleted , oC_ErrorCode_ReleaseError )
210  && ErrorCondition( oC_MemMan_FreeAllMemoryOfAllocator(&Allocator) , oC_ErrorCode_ReleaseError )
211  )
212  {
213  errorCode = oC_ErrorCode_None;
214  }
215  }
216  oC_IntMan_ExitCriticalSection();
217 
218  return errorCode;
219 }
220 
221 
222 //==========================================================================================================================================
234 //==========================================================================================================================================
236 {
237  bool reserved = false;
238 
239  if(
240  oC_Module_IsTurnedOn(oC_Module_Udp)
241  && oC_SaveIfFalse("UDP::IsPortReserved - ", Port != oC_Udp_Port_Empty , oC_ErrorCode_PortNotCorrect )
242  && oC_SaveIfFalse("UDP::IsPortReserved - ", Process == NULL || oC_Process_IsCorrect(Process) , oC_ErrorCode_ProcessNotCorrect )
243  )
244  {
245  reserved = IsPortReserved(Port);
246  }
247 
248  return reserved;
249 }
250 
251 //==========================================================================================================================================
280 //==========================================================================================================================================
281 oC_ErrorCode_t oC_Udp_ReservePort( oC_Udp_Port_t * Port , oC_Time_t Timeout )
282 {
283  oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
284 
285  if(
286  oC_Module_TurnOnVerification(&errorCode, oC_Module_Udp)
287  && ErrorCondition( isram(Port) , oC_ErrorCode_OutputAddressNotInRAM )
288  && ErrorCondition( Timeout >= 0 , oC_ErrorCode_TimeNotCorrect )
289  && ErrorCondition( *Port == 0 || IsSpecialPort(*Port) == false || iscurroot() , oC_ErrorCode_PermissionDenied )
290  )
291  {
292  oC_Timestamp_t endTimestamp = oC_KTime_GetTimestamp() + Timeout;
293  bool freePortFound = false;
294 
295  errorCode = oC_ErrorCode_PortNotAvailable;
296 
297  while(
298  freePortFound == false
299  && errorCode == oC_ErrorCode_PortNotAvailable
300  && ErrorCondition( oC_KTime_GetTimestamp() <= endTimestamp, oC_ErrorCode_PortNotAvailable )
301  )
302  {
303  Timeout = endTimestamp - oC_KTime_GetTimestamp();
304 
305  if( ErrorCondition( oC_Mutex_Take(ModuleBusy,Timeout) , oC_ErrorCode_ModuleBusy ) )
306  {
307  ReservationData_t * reservation = NULL;
308  oC_Udp_Port_t port = *Port;
309 
310  if(port == oC_Udp_Port_Empty)
311  {
312  /* As we are looking for free port - we cannot use ports that are reserved as specials */
313  for(port = oC_Udp_Port_NumberOfSpecialPorts; port > 0 && freePortFound == false; port++)
314  {
315  reservation = FindReservation(port,NULL);
316  freePortFound = reservation == NULL;
317  }
318  }
319  else
320  {
321  reservation = FindReservation(port,NULL);
322  freePortFound = reservation == NULL;
323  }
324 
325  if(ErrorCondition( freePortFound , oC_ErrorCode_PortNotAvailable ))
326  {
327  if(ErrorCondition( port != oC_Udp_Port_Empty , oC_ErrorCode_InternalDataAreDamaged ))
328  {
329  reservation = kmalloc( sizeof(ReservationData_t), &Allocator, AllocationFlags_Default );
330 
331  if(ErrorCondition( reservation != NULL , oC_ErrorCode_AllocationError ))
332  {
333  reservation->Busy = oC_Mutex_New( oC_Mutex_Type_Normal , &Allocator, AllocationFlags_Default );
334 
335  if( ErrorCondition( reservation->Busy != NULL , oC_ErrorCode_AllocationError ) )
336  {
337  reservation->Port = port;
338  reservation->Process = getcurprocess();
339 
340  bool addedToList = oC_List_PushBack(ReservedPorts,reservation,&Allocator);
341 
342  if( ErrorCondition( addedToList, oC_ErrorCode_CannotAddObjectToList ) )
343  {
344  errorCode = oC_ErrorCode_None;
345  }
346  else
347  {
348  oC_SaveIfFalse("UDP:Reserve - cannot release reservation memory ", kfree(reservation, AllocationFlags_Default), oC_ErrorCode_ReleaseError);
349  }
350  }
351  else
352  {
353  oC_SaveIfFalse("UDP:Reserve - cannot release reservation memory ", kfree(reservation, AllocationFlags_Default), oC_ErrorCode_ReleaseError);
354  }
355 
356  }
357  }
358  }
359  else
360  {
361  oC_Event_ClearStateBits( PortReleased, oC_Event_StateMask_Full );
362 
363  Timeout = endTimestamp - oC_KTime_GetTimestamp();
364 
365  if(*Port == oC_Udp_Port_Empty)
366  {
367  oC_Event_WaitForState( PortReleased, oC_Udp_Port_Empty, oC_Event_StateMask_DifferentThan, Timeout );
368  }
369  else
370  {
371  oC_Event_WaitForState( PortReleased, port, oC_Event_StateMask_Full, Timeout );
372  }
373  }
374 
375  oC_Mutex_Give( ModuleBusy );
376  }
377  }
378  }
379 
380  return errorCode;
381 }
382 
383 //==========================================================================================================================================
411 //==========================================================================================================================================
412 oC_ErrorCode_t oC_Udp_ReleasePort( oC_Udp_Port_t Port , oC_Time_t Timeout )
413 {
414  oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
415  oC_Timestamp_t endTimestamp = oC_KTime_GetTimestamp() + Timeout;
416 
417  if(
418  oC_Module_TurnOnVerification( &errorCode , oC_Module_Udp )
419  && ErrorCondition( Port != oC_Udp_Port_Empty , oC_ErrorCode_PortNotCorrect )
420  && ErrorCondition( Timeout >= 0 , oC_ErrorCode_TimeNotCorrect )
421  && ErrorCondition( oC_Mutex_Take(ModuleBusy,Timeout) , oC_ErrorCode_ModuleBusy )
422  )
423  {
424  ReservationData_t * reservation = FindReservation(Port,NULL);
425 
426  if(
427  ErrorCondition( reservation != NULL , oC_ErrorCode_PortNotReserved )
428  && ErrorCondition( reservation->Process == getcurprocess() , oC_ErrorCode_PortReservedByDifferentProcess )
429  && ErrorCondition( oC_Mutex_Take(reservation->Busy,oC_KTime_CalculateTimeout(endTimestamp)) , oC_ErrorCode_PortBusy )
430  )
431  {
432  bool mutexDeleted = oC_Mutex_Delete(&reservation->Busy, AllocationFlags_Default);
433  bool deletedFromList = oC_List_RemoveAll(ReservedPorts,reservation);
434  bool deleted = kfree(reservation,AllocationFlags_Default);
435 
436  if(
437  ErrorCondition( mutexDeleted , oC_ErrorCode_CannotDeleteObject )
438  && ErrorCondition( deletedFromList , oC_ErrorCode_CannotRemoveObjectFromList )
439  && ErrorCondition( deleted , oC_ErrorCode_ReleaseError )
440  )
441  {
442  oC_Event_SetState(PortReleased,Port);
443  errorCode = oC_ErrorCode_None;
444  }
445  }
446 
447  oC_Mutex_Give(ModuleBusy);
448  }
449 
450  return errorCode;
451 }
452 
453 //==========================================================================================================================================
480 //==========================================================================================================================================
481 oC_ErrorCode_t oC_Udp_ReleaseAllPortsReservedBy( oC_Process_t Process , oC_Time_t Timeout )
482 {
483  oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
484  oC_Timestamp_t endTimestamp = oC_KTime_GetTimestamp() + Timeout;
485 
486  if(
487  oC_Module_TurnOnVerification( &errorCode, oC_Module_Udp )
488  && ErrorCondition( getcuruser() == getrootuser() , oC_ErrorCode_PossibleOnlyForRoot )
489  && ErrorCondition( Timeout >= 0 , oC_ErrorCode_TimeNotCorrect )
490  && ErrorCondition( oC_Mutex_Take(ModuleBusy,Timeout) , oC_ErrorCode_ModuleBusy )
491  )
492  {
493  ReservationData_t * reservation = FindReservation(oC_Udp_Port_Empty, Process);
494 
495  errorCode = oC_ErrorCode_None;
496 
497  while(
498  reservation != NULL
499  && ErrorCondition( oC_KTime_GetTimestamp() <= endTimestamp , oC_ErrorCode_Timeout )
500  )
501  {
502  reservation->Process = getcurprocess();
503 
504  Timeout = endTimestamp - oC_KTime_GetTimestamp();
505 
506  ErrorCode( oC_Udp_ReleasePort( reservation->Port, Timeout ) );
507 
508  reservation = FindReservation( oC_Udp_Port_Empty, Process );
509  }
510 
511  oC_Mutex_Give(ModuleBusy);
512  }
513 
514  return errorCode;
515 }
516 
517 //==========================================================================================================================================
521 //==========================================================================================================================================
523 {
524  return oC_Net_GetMaximumPacketDataSize(Type) - sizeof(oC_Udp_Header_t);
525 }
526 
527 //==========================================================================================================================================
546 //==========================================================================================================================================
547 oC_Udp_Packet_t* oC_Udp_Packet_New( Allocator_t PacketAllocator , oC_Net_PacketType_t Type , const void * Data , uint16_t Size )
548 {
549  oC_Udp_Packet_t * packet = NULL;
550  uint16_t packetSize = Size + sizeof(oC_Udp_Header_t);
551 
552  if(
553  oC_SaveIfFalse("Udp::PacketNew: " , oC_Module_IsTurnedOn(oC_Module_Udp) , oC_ErrorCode_ModuleNotStartedYet )
554  && oC_SaveIfFalse("Udp::PacketNew: Packet Type incorrect - " , Type == oC_Net_PacketType_IPv4
555  || Type == oC_Net_PacketType_IPv6 , oC_ErrorCode_TypeNotCorrect )
556  && oC_SaveIfFalse("Udp::PacketNew: Size is not correct - " , Size > 0 , oC_ErrorCode_SizeNotCorrect )
557  && oC_SaveIfFalse("Udp::PacketNew: Size is not correct - " , Size <= oC_Udp_Packet_GetMaximumDataSize(Type) , oC_ErrorCode_SizeTooBig )
558  && oC_SaveIfFalse("Udp::PacketNew: Data address incorrect - " , Data == NULL || isaddresscorrect(Data) , oC_ErrorCode_WrongAddress )
559  && oC_SaveIfFalse("Udp::PacketNew: Allocator incorrect - " , isaddresscorrect(PacketAllocator) , oC_ErrorCode_WrongAddress )
560  )
561  {
562  packet = (oC_Udp_Packet_t*) oC_Net_Packet_New( PacketAllocator, Type, NULL, packetSize );
563 
564  if(oC_SaveIfFalse("Udp::PacketNew: Cannot allocate memory for a packet - ", packet != NULL , oC_ErrorCode_AllocationError))
565  {
566  oC_Udp_Datagram_t * datagram = oC_Net_Packet_GetDataReference(&packet->Packet);
567 
568  datagram->Header.Length = Size + sizeof(oC_Udp_Header_t);
569 
570  if(Data != NULL)
571  {
572  void * dataDestination = datagram;
573 
574  dataDestination += sizeof(oC_Udp_Header_t);
575 
576  memcpy(dataDestination,Data,Size);
577  }
578  }
579  }
580 
581  return packet;
582 }
583 
584 //==========================================================================================================================================
588 //==========================================================================================================================================
590 {
591  bool success = false;
592 
593  if(isram(Packet) && isram(*Packet))
594  {
595  success = kfree(*Packet,AllocationFlags_Default);
596  *Packet = NULL;
597  }
598 
599  return success;
600 }
601 
602 //==========================================================================================================================================
606 //==========================================================================================================================================
607 uint16_t oC_Udp_Packet_GetDataSize( const oC_Udp_Packet_t * Packet )
608 {
609  uint16_t size = 0;
610 
611  if(isaddresscorrect(Packet))
612  {
613  oC_Udp_Datagram_t * datagram = oC_Net_Packet_GetDataReference((void*)&Packet->Packet);
614 
615  if(isaddresscorrect(datagram) && datagram->Header.Length >= sizeof(oC_Udp_Header_t) )
616  {
617  size = datagram->Header.Length - sizeof(oC_Udp_Header_t);
618  }
619  }
620 
621  return size;
622 }
623 
624 //==========================================================================================================================================
628 //==========================================================================================================================================
629 bool oC_Udp_Packet_SetData( oC_Udp_Packet_t * Packet , const void * Data , uint16_t Size )
630 {
631  bool success = false;
632 
633  if(isram(Packet) && isaddresscorrect(Data) && Size > 0 && Size <= oC_Udp_Packet_GetDataSize( Packet ) )
634  {
635  oC_Udp_Datagram_t * datagram = oC_Net_Packet_GetDataReference(&Packet->Packet);
636 
637  if(isram(datagram))
638  {
639  memcpy(datagram->Data,Data,Size);
640  success = true;
641  }
642  }
643 
644  return success;
645 }
646 
647 //==========================================================================================================================================
651 //==========================================================================================================================================
652 oC_ErrorCode_t oC_Udp_Packet_ReadData( const oC_Udp_Packet_t * Packet , void * outData , uint16_t Size )
653 {
654  oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
655 
656  if(
657  ErrorCondition( isaddresscorrect(Packet) , oC_ErrorCode_WrongAddress )
658  && ErrorCondition( isram(outData) , oC_ErrorCode_OutputAddressNotInRAM )
659  && ErrorCondition( Size >= oC_Udp_Packet_GetDataSize( Packet ) , oC_ErrorCode_OutputBufferTooSmall )
660  )
661  {
662  oC_Udp_Datagram_t * datagram = oC_Net_Packet_GetDataReference((void*)&Packet->Packet);
663 
664  if( ErrorCondition( isram(datagram) , oC_ErrorCode_PacketNotCorrect) )
665  {
666  memcpy( outData, datagram->Data, Size );
667  errorCode = oC_ErrorCode_None;
668  }
669  }
670 
671  return errorCode;
672 }
673 
674 //==========================================================================================================================================
678 //==========================================================================================================================================
680 {
681  void * data = NULL;
682  oC_Udp_Datagram_t * datagram = oC_Net_Packet_GetDataReference(&Packet->Packet);
683 
684  if(isaddresscorrect(datagram))
685  {
686  data = datagram->Data;
687  }
688 
689  return data;
690 }
691 
692 //==========================================================================================================================================
731 //==========================================================================================================================================
732 oC_ErrorCode_t oC_Udp_Send( oC_Netif_t Netif , oC_Udp_Port_t LocalPort , const oC_Net_Address_t * Destination, oC_Udp_Packet_t * Packet , oC_Time_t Timeout )
733 {
734  oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
735  ReservationData_t* reservation = FindReservation(LocalPort,NULL);
736  uint16_t packetSize = oC_Udp_Packet_GetDataSize(Packet);
738  oC_Net_AddressType_t addressType = isaddresscorrect(Destination) ? Destination->Type : 0;
739  oC_Timestamp_t timestamp = oC_KTime_GetTimestamp();
740  oC_Timestamp_t endTimestamp = timestamp + Timeout;
741 
742  if(
743  oC_Module_TurnOnVerification( &errorCode , oC_Module_Udp )
744  && ErrorCondition( Netif == NULL || oC_Netif_IsCorrect(Netif) , oC_ErrorCode_NetifNotCorrect )
745  && ErrorCondition( LocalPort > 0 , oC_ErrorCode_PortNotCorrect )
746  && ErrorCondition( isram(Packet) , oC_ErrorCode_OutputAddressNotInRAM )
747  && ErrorCondition( isaddresscorrect(Destination) , oC_ErrorCode_WrongAddress )
748  && ErrorCondition( oC_Net_IsAddressCorrect(Destination) , oC_ErrorCode_IpAddressNotCorrect )
749  && ErrorCondition( Destination->Port > 0 , oC_ErrorCode_PortNotCorrect )
750  && ErrorCondition( ((oC_Net_PacketType_t)addressType) == packetType , oC_ErrorCode_TypeNotCorrect )
751  && ErrorCondition( packetSize > 0 , oC_ErrorCode_SizeNotCorrect )
752  && ErrorCondition( Timeout > 0 , oC_ErrorCode_TimeNotCorrect )
753  && ErrorCondition( reservation != NULL , oC_ErrorCode_PortNotReserved )
754  && ErrorCondition( reservation->Process == getcurprocess() , oC_ErrorCode_PortReservedByDifferentProcess )
755  && ErrorCondition( packetSize <= oC_Udp_Packet_GetMaximumDataSize(Destination->Type) , oC_ErrorCode_SizeTooBig )
756  && ErrorCondition( oC_Mutex_Take(ModuleBusy,Timeout) , oC_ErrorCode_ModuleBusy )
757  )
758  {
759  oC_Udp_Datagram_t * datagram = oC_Net_Packet_GetDataReference(&Packet->Packet);
760 
761  Netif = Netif == NULL ? oC_NetifMan_GetNetifForAddress(Destination) : Netif;
762 
763  oC_Mutex_Give(ModuleBusy);
764 
765  if(
766  ErrorCondition( oC_Netif_IsCorrect(Netif) , oC_ErrorCode_CannotFindNetifForTheAddress )
767  && ErrorCondition( oC_Mutex_Take(reservation->Busy, oC_KTime_CalculateTimeout(endTimestamp)) , oC_ErrorCode_PortBusy )
768  && ErrorCondition( isram(datagram) , oC_ErrorCode_PacketNotCorrect )
769  && ErrorCondition( packetType == oC_Net_PacketType_IPv4 , oC_ErrorCode_NotImplemented )
770  )
771  {
772  if(packetType == oC_Net_PacketType_IPv4)
773  {
774  Packet->Packet.IPv4.Header.DF = 0;
775  Packet->Packet.IPv4.Header.DestinationIp = Destination->IPv4;
776  Packet->Packet.IPv4.Header.SourceIp = oC_Netif_GetIpv4Address(Netif);
777  Packet->Packet.IPv4.Header.FragmentOffset = 0;
778  Packet->Packet.IPv4.Header.ID = 0;
779  Packet->Packet.IPv4.Header.IHL = 5;
780  Packet->Packet.IPv4.Header.MF = 0;
781  Packet->Packet.IPv4.Header.Protocol = oC_Net_Protocol_UDP;
782  Packet->Packet.IPv4.Header.QoS = 0;
783  Packet->Packet.IPv4.Header.TTL = 0xFF;
784  Packet->Packet.IPv4.Header.Checksum = 0;
785 
786  }
787  else
788  {
789  memcpy(&Packet->Packet.IPv6.Header.Destination,&Destination->IPv6,sizeof(oC_Net_Ipv6_t));
790  oC_Netif_ReadIpv6Address(Netif,&Packet->Packet.IPv6.Header.Source);
791 
792  oC_SaveError("UDP::Send - Function is not implemented for IPv6!", oC_ErrorCode_NotImplemented);
793  }
794 
795  datagram->Header.DestinationPort = Destination->Port;
796  datagram->Header.SourcePort = LocalPort;
797  datagram->Header.Checksum = CalculateChecksum(Packet);
798 
800 
801  errorCode = oC_Netif_SendPacket( Netif, &Packet->Packet, oC_KTime_CalculateTimeout(endTimestamp) );
802 
804  }
805 
806  }
807 
808  return errorCode;
809 }
810 
811 //==========================================================================================================================================
851 //==========================================================================================================================================
852 oC_ErrorCode_t oC_Udp_Receive( oC_Netif_t Netif , oC_Udp_Port_t LocalPort , oC_Udp_Packet_t * Packet, oC_Time_t Timeout )
853 {
854  oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
855  ReservationData_t* reservation = FindReservation(LocalPort,NULL);
856  uint16_t packetSize = oC_Udp_Packet_GetDataSize(Packet);
857  oC_Timestamp_t endTimestamp = oC_KTime_GetTimestamp() + Timeout;
858 
859  if(
860  oC_Module_TurnOnVerification( &errorCode, oC_Module_Udp )
861  && ErrorCondition( Netif == NULL || oC_Netif_IsCorrect(Netif) , oC_ErrorCode_NetifNotCorrect )
862  && ErrorCondition( LocalPort > 0 , oC_ErrorCode_PortNotCorrect )
863  && ErrorCondition( Timeout > 0 , oC_ErrorCode_TimeNotCorrect )
864  && ErrorCondition( isram(Packet) , oC_ErrorCode_OutputAddressNotInRAM )
865  && ErrorCondition( reservation != NULL , oC_ErrorCode_PortNotReserved )
866  && ErrorCondition( reservation->Process == getcurprocess() , oC_ErrorCode_PortReservedByDifferentProcess )
867  && ErrorCondition( packetSize > 0 , oC_ErrorCode_SizeNotCorrect )
868  && ErrorCondition( oC_Mutex_Take(reservation->Busy,oC_KTime_CalculateTimeout(endTimestamp)) , oC_ErrorCode_PortBusy )
869  && ErrorCondition( oC_Mutex_Take(ModuleBusy,oC_KTime_CalculateTimeout(endTimestamp)) , oC_ErrorCode_ModuleBusy )
870  )
871  {
872  oC_Net_Address_t addressFilter = {
873  .Type = oC_Net_Packet_GetType(&Packet->Packet) ,
874  .Protocol = oC_Net_Protocol_UDP,
875  .Port = 0 ,
876  .IPv4 = 0 ,
877  .IPv6.LowPart = 0 ,
878  .IPv6.HighPart = 0 ,
879  };
880  oC_Udp_Datagram_t * datagram = NULL;
881  oC_Netif_t receivedFromNetif = NULL;
882  PacketFilterData_t filterData = {
883  .DestinationPort = LocalPort ,
884  .ExpectedNetif = Netif ,
885  };
886 
887  oC_Mutex_Give(ModuleBusy);
888 
889  if(ErrorCode(oC_NetifMan_ReceivePacket(&addressFilter, &Packet->Packet, gettimeout(endTimestamp), &receivedFromNetif, PacketFilterFunction, &filterData)))
890  {
891  datagram = oC_Net_Packet_GetDataReference(&Packet->Packet);
892 
893  if(ErrorCondition( isram(datagram) , oC_ErrorCode_PacketNotCorrect ))
894  {
896  errorCode = oC_ErrorCode_None;
897  }
898  }
899  }
900 
901  return errorCode;
902 }
903 
904 //==========================================================================================================================================
925 //==========================================================================================================================================
926 oC_ErrorCode_t oC_Udp_CalculateChecksum( oC_Udp_Packet_t * Packet , bool * outChecksumCorrect , uint16_t * outExpectedChecksum )
927 {
928  oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
929 
930  if(
931  oC_Module_TurnOnVerification(&errorCode , oC_Module_Udp)
932  && ErrorCondition( isram(Packet) , oC_ErrorCode_AddressNotInRam )
933  && ErrorCondition( outChecksumCorrect == NULL || isram(outChecksumCorrect) , oC_ErrorCode_OutputAddressNotInRAM )
934  && ErrorCondition( outExpectedChecksum == NULL || isram(outExpectedChecksum) , oC_ErrorCode_OutputAddressNotInRAM )
935  )
936  {
937  oC_Udp_Datagram_t * datagram = oC_Net_Packet_GetDataReference(&Packet->Packet);
938 
939  if( ErrorCondition(isram(datagram), oC_ErrorCode_PacketNotCorrect) )
940  {
941  uint16_t checksum = CalculateChecksum(Packet);
942 
943  if(checksum == 0)
944  {
945  checksum = 0xFFFF;
946  }
947 
948  if(outChecksumCorrect != NULL)
949  {
950  *outChecksumCorrect = checksum == datagram->Header.Checksum || datagram->Header.Checksum == 0;
951  }
952 
953  if(outExpectedChecksum)
954  {
955  *outExpectedChecksum = checksum;
956  }
957 
958  errorCode = oC_ErrorCode_None;
959  }
960  }
961 
962  return errorCode;
963 }
964 
966 #undef _________________________________________FUNCTIONS_SECTION_________________________________________________________________________
967 
973 #define _________________________________________LOCAL_FUNCTIONS_SECTION____________________________________________________________________
974 
975 //==========================================================================================================================================
979 //==========================================================================================================================================
980 static bool PacketFilterFunction( oC_Net_Packet_t * Packet , const void * Parameter , oC_Netif_t Netif )
981 {
982  bool packetForUs = false;
984  const PacketFilterData_t* filterData = Parameter;
985 
986  if(header != NULL && Parameter != NULL)
987  {
988  oC_Udp_Port_t destinationPort = filterData->DestinationPort;
989 
990  if(oC_Net_ConvertUint16FromNetworkEndianess(header->DestinationPort) == destinationPort )
991  {
992  packetForUs = filterData->ExpectedNetif == NULL || filterData->ExpectedNetif == Netif;
993  }
994  }
995 
996  return packetForUs;
997 }
998 
999 //==========================================================================================================================================
1003 //==========================================================================================================================================
1005 {
1006  ReservationData_t * foundReservation = NULL;
1007 
1008  foreach(ReservedPorts,reservation)
1009  {
1010  if(
1011  (reservation->Port == Port && Port != oC_Udp_Port_Empty )
1012  || (reservation->Process == Process && Process != NULL )
1013  )
1014  {
1015  foundReservation = reservation;
1016  }
1017  }
1018 
1019  return foundReservation;
1020 }
1021 
1022 //==========================================================================================================================================
1026 //==========================================================================================================================================
1027 static uint16_t CalculateChecksum( oC_Udp_Packet_t * Packet )
1028 {
1029  uint32_t checksum = 0;
1030  oC_Net_PacketType_t packetType = oC_Net_Packet_GetType(&Packet->Packet);
1031 
1032  if(packetType == oC_Net_PacketType_IPv4)
1033  {
1034  uint16_t * srcAddr = (uint16_t*)&Packet->IPv4.Header.SourceIp;
1035  uint16_t * dstAddr = (uint16_t*)&Packet->IPv4.Header.DestinationIp;
1036 
1037  checksum += srcAddr[1];
1038  checksum += srcAddr[0];
1039 
1040  checksum += dstAddr[1];
1041  checksum += dstAddr[0];
1042 
1043  checksum += oC_Net_Protocol_UDP;
1044 
1045  checksum += Packet->IPv4.UdpDatagram.Header.Length;
1046 
1047  checksum += Packet->IPv4.UdpDatagram.Header.SourcePort;
1048 
1049  checksum += Packet->IPv4.UdpDatagram.Header.DestinationPort;
1050 
1051  checksum += Packet->IPv4.UdpDatagram.Header.Length;
1052 
1053  while(checksum >> 16)
1054  {
1055  checksum = (checksum & 0xFFFF) + (checksum >> 16);
1056  }
1057 
1058  checksum = oC_Net_CalculateChecksum(Packet->IPv4.UdpDatagram.Data, oC_Udp_Packet_GetDataSize(Packet), checksum, true, true);
1059  }
1060 
1061  return (uint16_t)checksum;
1062 }
1063 
1064 //==========================================================================================================================================
1068 //==========================================================================================================================================
1069 static bool IsSpecialPort( oC_Udp_Port_t Port )
1070 {
1071  return Port < oC_Udp_Port_NumberOfSpecialPorts;
1072 }
1073 
1074 //==========================================================================================================================================
1078 //==========================================================================================================================================
1079 static bool IsPortReserved( oC_Udp_Port_t Port )
1080 {
1081  ReservationData_t * reservationData = FindReservation(Port,NULL);
1082  return reservationData != NULL;
1083 }
1084 
1085 //==========================================================================================================================================
1089 //==========================================================================================================================================
1091 {
1096 }
1097 
1098 //==========================================================================================================================================
1102 //==========================================================================================================================================
1104 {
1109 }
1110 
1111 #undef _________________________________________LOCAL_FUNCTIONS_SECTION____________________________________________________________________
1112 
oC_Net_Ipv4_t SourceIp
Source IP address.
Definition: oc_net.h:231
Packet in type IPv4.
Definition: oc_net.h:177
bool oC_Event_WaitForState(oC_Event_t Event, oC_Event_State_t State, oC_Event_StateMask_t StateMask, oC_Time_t Timeout)
Definition: oc_event.c:245
uint32_t Length
Length of the packet in bytes.
Definition: oc_net.h:222
oC_ErrorCode_t oC_Udp_ReleaseAllPortsReservedBy(oC_Process_t Process, oC_Time_t Timeout)
releases all ports reserved by the process
Definition: oc_udp.c:481
struct PACKED oC_Udp_Header_t
stores UDP header
uint32_t QoS
Quality of Service or Type of Service - describes the priority of the packet
Definition: oc_net.h:221
const char * Name
Definition: oc_stdlib.h:161
static oC_Net_Packet_t * oC_Net_Packet_New(Allocator_t Allocator, oC_Net_PacketType_t Type, void *Data, uint16_t Size)
allocates memory for a packet
Definition: oc_net.h:1511
bool oC_Udp_IsPortReserved(oC_Udp_Port_t Port, oC_Process_t Process)
checks if the given UDP port is reserved
Definition: oc_udp.c:235
oC_Udp_Port_t
stores UDP port number
Definition: oc_udp.h:74
static uint16_t oC_Net_ConvertUint16FromNetworkEndianess(uint16_t v)
converts uint16_t from network byte order
Definition: oc_net.h:579
oC_Net_Ipv4PacketHeader_t Header
Header of the IPv4 packet.
Definition: oc_net.h:276
identifier for allocations
Definition: oc_stdlib.h:159
User Datagram Protocol.
Definition: oc_net.h:160
uint32_t DF
Don&#39;t Fragment - packet can be fragmented or not
Definition: oc_net.h:226
bool oC_MemMan_FreeAllMemoryOfAllocator(Allocator_t Allocator)
release all memory of allocator
Definition: oc_memman.c:985
The file with interface for process manager.
stores UDP packet
Definition: oc_udp.h:305
oC_ErrorCode_t oC_NetifMan_ReceivePacket(const oC_Net_Address_t *Address, oC_Net_Packet_t *outPacket, oC_Time_t Timeout, oC_Netif_t *outNetif, oC_NetifMan_PacketFilterFunction_t FilterFunction, const void *Parameter)
receives packet from the network
Definition: oc_netifman.c:763
number of special ports, that are reserved for special service
Definition: oc_udp.h:237
Packet in type IPv6.
Definition: oc_net.h:178
Stores interface of netif manager module.
stores network address
Definition: oc_net.h:441
oC_Net_AddressType_t
stores type of the network address
Definition: oc_net.h:427
oC_Net_PacketType_t
stores type of the packet
Definition: oc_net.h:174
bool oC_Netif_IsCorrect(oC_Netif_t Netif)
checks if the Netif object is correct
Definition: oc_netif.c:351
static oC_Net_PacketType_t oC_Net_Packet_GetType(const oC_Net_Packet_t *Packet)
returns type of the packet
Definition: oc_net.h:1370
static void ConvertHeaderToNetworkEndianess(oC_Udp_Header_t *Header)
converts UDP header to network endianess
Definition: oc_udp.c:1090
static uint16_t oC_Net_GetMaximumPacketDataSize(oC_Net_PacketType_t Type)
returns maximum size of the packet data
Definition: oc_net.h:1058
static uint16_t oC_Net_ConvertUint16ToNetworkEndianess(uint16_t v)
converts uint16_t to network byte order
Definition: oc_net.h:545
static void ConvertHeaderFromNetworkEndianess(oC_Udp_Header_t *Header)
converts UDP header from network endianess
Definition: oc_udp.c:1103
bool oC_Udp_Packet_Delete(oC_Udp_Packet_t **Packet)
release memory allocated for a UDP packet
Definition: oc_udp.c:589
oC_ErrorCode_t oC_Udp_ReservePort(oC_Udp_Port_t *Port, oC_Time_t Timeout)
reserves a UDP port
Definition: oc_udp.c:281
The file with interface for the module library.
oC_ErrorCode_t oC_Udp_TurnOn(void)
turns on UDP module
Definition: oc_udp.c:132
static bool oC_Module_IsTurnedOn(oC_Module_t Module)
checks if the module is turned on
Definition: oc_module.h:121
The file with interface for event module.
oC_ErrorCode_t oC_Udp_CalculateChecksum(oC_Udp_Packet_t *Packet, bool *outChecksumCorrect, uint16_t *outExpectedChecksum)
Calculates checksum for UDP packet.
Definition: oc_udp.c:926
oC_ErrorCode_t oC_Udp_ReleasePort(oC_Udp_Port_t Port, oC_Time_t Timeout)
releases a port
Definition: oc_udp.c:412
oC_Net_Ipv4_t oC_Netif_GetIpv4Address(oC_Netif_t Netif)
returns address of the network interface
Definition: oc_netif.c:1427
uint32_t FragmentOffset
Field to identify position of fragment within original packet.
Definition: oc_net.h:224
oC_ErrorCode_t oC_Udp_TurnOff(void)
turns off UDP module
Definition: oc_udp.c:188
stores network packet
Definition: oc_net.h:302
oC_Net_Ipv4_t IPv4
Address in IPv4 version.
Definition: oc_net.h:446
uint32_t ID
ID value for reconstruction the packet from segments.
Definition: oc_net.h:223
The file with list library.
The file with interface for interrupt manager.
uint16_t oC_Udp_Packet_GetDataSize(const oC_Udp_Packet_t *Packet)
returns size of the data inside UDP packet
Definition: oc_udp.c:607
uint32_t IHL
4 bits, that contain Internet Header Length, which is the length of the header in multiples of 4 (num...
Definition: oc_net.h:220
uint16_t oC_Udp_Packet_GetMaximumDataSize(oC_Net_PacketType_t Type)
returns maximum size of the data for UDP packet
Definition: oc_udp.c:522
Special value for marks port as not filled.
Definition: oc_udp.h:76
oC_Net_Ipv6_t IPv6
Address in IPv6 version.
Definition: oc_net.h:447
static uint16_t CalculateChecksum(oC_Udp_Packet_t *Packet)
calculates checksum for a packet
Definition: oc_udp.c:1027
static bool oC_Net_IsAddressCorrect(const oC_Net_Address_t *Address)
returns true if the given address is correct
Definition: oc_net.h:918
The file with interface for mutex managing.
Stores UDP interface.
static void oC_Module_TurnOn(oC_Module_t Module)
sets module as turned on
Definition: oc_module.h:170
oC_ErrorCode_t oC_Udp_Packet_ReadData(const oC_Udp_Packet_t *Packet, void *outData, uint16_t Size)
reads data of the UDP packet
Definition: oc_udp.c:652
uint32_t TTL
Time to live - number of hops the packet is allowed to pass before it dies.
Definition: oc_net.h:228
uint8_t Data[IPv4_MAXIMUM_DATA_LENGTH]
Data of the packet.
Definition: oc_net.h:277
oC_Udp_Packet_t * oC_Udp_Packet_New(Allocator_t PacketAllocator, oC_Net_PacketType_t Type, const void *Data, uint16_t Size)
allocates memory for a UDP packet
Definition: oc_udp.c:547
oC_Net_Ipv6_t Source
Source IP address.
Definition: oc_net.h:257
oC_Net_Ipv4Packet_t IPv4
Packet in format IPv4.
Definition: oc_net.h:304
uint16_t SourcePort
This field identifies the sender&#39;s port when meaningful and should be assumed to be the port to reply...
Definition: oc_udp.h:249
uint32_t Checksum
Header checksum - number used for errors detection.
Definition: oc_net.h:230
oC_Netif_t oC_NetifMan_GetNetifForAddress(const oC_Net_Address_t *Destination)
returns network interface according to destination address
Definition: oc_netifman.c:415
The file with memory manager interface.
static void * oC_Net_Packet_GetDataReference(oC_Net_Packet_t *Packet)
returns reference to the payload in the packet
Definition: oc_net.h:1419
uint16_t DestinationPort
This field identifies the receiver&#39;s port and is required.
Definition: oc_udp.h:250
uint32_t Protocol
Contains selected protocol (TCP/UDP/ICMP,etc).
Definition: oc_net.h:229
uint32_t MF
More Fragments - whether more fragments of a packet follow
Definition: oc_net.h:225
bool oC_Udp_Packet_SetData(oC_Udp_Packet_t *Packet, const void *Data, uint16_t Size)
sets data inside UDP packet
Definition: oc_udp.c:629
static uint16_t oC_Net_CalculateChecksum(const void *Buffer, uint16_t Size, uint16_t InitialValue, bool ConvertEndianess, bool PrepareChecksumToSend)
Definition: oc_net.h:1581
static bool oC_Module_TurnOffVerification(oC_ErrorCode_t *outErrorCode, oC_Module_t Module)
verify if module is turned off
Definition: oc_module.h:155
static bool IsSpecialPort(oC_Udp_Port_t Port)
returns true if port is special port
Definition: oc_udp.c:1069
static const oC_Allocator_t Allocator
Definition: oc_eth.c:152
oC_ErrorCode_t oC_Udp_Send(oC_Netif_t Netif, oC_Udp_Port_t LocalPort, const oC_Net_Address_t *Destination, oC_Udp_Packet_t *Packet, oC_Time_t Timeout)
sends UDP packet
Definition: oc_udp.c:732
static bool oC_Module_TurnOnVerification(oC_ErrorCode_t *outErrorCode, oC_Module_t Module)
verify if module is turned on
Definition: oc_module.h:138
oC_ErrorCode_t oC_Netif_SendPacket(oC_Netif_t Netif, oC_Net_Packet_t *Packet, oC_Time_t Timeout)
sends packet by using the network interface
Definition: oc_netif.c:572
oC_Net_Ipv4_t DestinationIp
Destination IP address.
Definition: oc_net.h:232
oC_ErrorCode_t oC_Udp_Receive(oC_Netif_t Netif, oC_Udp_Port_t LocalPort, oC_Udp_Packet_t *Packet, oC_Time_t Timeout)
receives UDP packet
Definition: oc_udp.c:852
static bool PacketFilterFunction(oC_Net_Packet_t *Packet, const void *Parameter, oC_Netif_t Netif)
function used in NetifMan for filtering packets
Definition: oc_udp.c:980
void * oC_Udp_Packet_GetDataReference(oC_Udp_Packet_t *Packet)
returns reference to the data inside UDP packet
Definition: oc_udp.c:679
bool oC_Netif_ReadIpv6Address(oC_Netif_t Netif, oC_Net_Ipv6_t *outAddress)
reads IPv6 address of the network interface
Definition: oc_netif.c:1445
static ReservationData_t * FindReservation(oC_Udp_Port_t Port, oC_Process_t Process)
finds reservation of port or process
Definition: oc_udp.c:1004
oC_Net_AddressType_t Type
Type of the address stored inside.
Definition: oc_net.h:443
oC_Net_Ipv6Packet_t IPv6
Packet in format IPv6.
Definition: oc_net.h:305
static bool IsPortReserved(oC_Udp_Port_t Port)
checks if port is reserved
Definition: oc_udp.c:1079
oC_Net_Port_t Port
Port of the address.
Definition: oc_net.h:450
oC_Net_Ipv6_t Destination
Destination IP address.
Definition: oc_net.h:258
stores IPv6 address
Definition: oc_net.h:142
#define NULL
pointer to a zero
Definition: oc_null.h:37
static void oC_Module_TurnOff(oC_Module_t Module)
sets module as turned off
Definition: oc_module.h:185