2 * Acess2 Networking Stack
3 * - By John Hodge (thePowersGang)
6 * - Scatter-gather handling
9 #include "include/buffer.h"
31 tIPStackBuffer *IPStack_Buffer_CreateBuffer(int MaxBuffers)
35 ret = malloc( sizeof(*ret) + MaxBuffers * sizeof(ret->SubBuffers[0]) );
37 ret->MaxSubBufffers = MaxBuffers;
40 memset(&ret->lBufferLock, 0, sizeof(ret->lBufferLock));
41 memset(ret->SubBuffers, 0, MaxBuffers * sizeof(ret->SubBuffers[0]));
45 void IPStack_Buffer_ClearBuffer(tIPStackBuffer *Buffer)
48 IPStack_Buffer_LockBuffer(Buffer);
49 for( int i = 0; i < Buffer->nSubBuffers; i ++ )
51 if( Buffer->SubBuffers[i].Cb == NULL )
53 Buffer->SubBuffers[i].Cb(
54 Buffer->SubBuffers[i].CbArg,
55 Buffer->SubBuffers[i].PreLength,
56 Buffer->SubBuffers[i].PostLength,
57 Buffer->SubBuffers[i].Data
60 Buffer->nSubBuffers = 0;
61 IPStack_Buffer_UnlockBuffer(Buffer);
64 void IPStack_Buffer_DestroyBuffer(tIPStackBuffer *Buffer)
67 IPStack_Buffer_ClearBuffer(Buffer);
68 Buffer->MaxSubBufffers = 0;
72 void IPStack_Buffer_LockBuffer(tIPStackBuffer *Buffer)
75 Mutex_Acquire(&Buffer->lBufferLock);
77 void IPStack_Buffer_UnlockBuffer(tIPStackBuffer *Buffer)
80 Mutex_Release(&Buffer->lBufferLock);
83 void IPStack_Buffer_AppendSubBuffer(tIPStackBuffer *Buffer,
84 size_t HeaderLen, size_t FooterLen, const void *Data,
85 tIPStackBufferCb Cb, void *Arg
89 if( Buffer->nSubBuffers == Buffer->MaxSubBufffers ) {
91 Log_Error("IPStack", "Buffer %p only had %i sub-buffers allocated, which was not enough",
92 Buffer, Buffer->MaxSubBufffers);
96 int index = Buffer->nSubBuffers++;
97 Buffer->TotalLength += HeaderLen + FooterLen;
99 Buffer->SubBuffers[index].Data = Data;
100 Buffer->SubBuffers[index].PreLength = HeaderLen;
101 Buffer->SubBuffers[index].PostLength = FooterLen;
102 Buffer->SubBuffers[index].Cb = Cb;
103 Buffer->SubBuffers[index].CbArg = Arg;
106 size_t IPStack_Buffer_GetLength(tIPStackBuffer *Buffer)
109 return Buffer->TotalLength;
112 size_t IPStack_Buffer_GetData(tIPStackBuffer *Buffer, void *Dest, size_t MaxBytes)
116 size_t rem_space = MaxBytes;
119 for( int i = Buffer->nSubBuffers; i -- && rem_space != 0; )
121 len = MIN(Buffer->SubBuffers[i].PreLength, rem_space);
123 Buffer->SubBuffers[i].Data,
129 for( int i = 0; i < Buffer->nSubBuffers && rem_space; i ++ )
131 if( Buffer->SubBuffers[i].PostLength == 0 )
134 len = MIN(Buffer->SubBuffers[i].PostLength, rem_space);
136 (Uint8*)Buffer->SubBuffers[i].Data + Buffer->SubBuffers[i].PreLength,
143 return MaxBytes - rem_space;
146 void *IPStack_Buffer_CompactBuffer(tIPStackBuffer *Buffer, size_t *Length)
149 void *ret = malloc(Buffer->TotalLength);
155 *Length = Buffer->TotalLength;
157 IPStack_Buffer_GetData(Buffer, ret, Buffer->TotalLength);
162 int IPStack_Buffer_GetBuffer(tIPStackBuffer *Buffer, int Index, size_t *Length, const void **DataPtr)
165 if( Index == -1 ) Index = 0;
167 if( Index >= Buffer->nSubBuffers*2 ) {
171 if( Index >= Buffer->nSubBuffers )
174 Index -= Buffer->nSubBuffers;
176 // Bit of a hack to avoid multiple calls which return a zero length
177 while( !Buffer->SubBuffers[Index].PostLength )
179 if( Index++ == Buffer->nSubBuffers )
184 *DataPtr = (Uint8*)Buffer->SubBuffers[Index].Data + Buffer->SubBuffers[Index].PreLength;
186 *Length = Buffer->SubBuffers[Index].PostLength;
188 return (Index + 1) + Buffer->nSubBuffers;
193 Index = Buffer->nSubBuffers - Index - 1;
196 *DataPtr = Buffer->SubBuffers[Index].Data;
198 *Length = Buffer->SubBuffers[Index].PreLength;