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]) );
36 ret->MaxSubBufffers = MaxBuffers;
39 memset(&ret->lBufferLock, 0, sizeof(ret->lBufferLock));
40 memset(ret->SubBuffers, 0, MaxBuffers * sizeof(ret->SubBuffers[0]));
44 void IPStack_Buffer_ClearBuffer(tIPStackBuffer *Buffer)
46 IPStack_Buffer_LockBuffer(Buffer);
47 for( int i = 0; i < Buffer->nSubBuffers; i ++ )
49 if( Buffer->SubBuffers[i].Cb == NULL )
51 Buffer->SubBuffers[i].Cb(
52 Buffer->SubBuffers[i].CbArg,
53 Buffer->SubBuffers[i].PreLength,
54 Buffer->SubBuffers[i].PostLength,
55 Buffer->SubBuffers[i].Data
58 Buffer->nSubBuffers = 0;
59 IPStack_Buffer_UnlockBuffer(Buffer);
62 void IPStack_Buffer_DestroyBuffer(tIPStackBuffer *Buffer)
64 IPStack_Buffer_ClearBuffer(Buffer);
65 Buffer->MaxSubBufffers = 0;
69 void IPStack_Buffer_LockBuffer(tIPStackBuffer *Buffer)
71 Mutex_Acquire(&Buffer->lBufferLock);
73 void IPStack_Buffer_UnlockBuffer(tIPStackBuffer *Buffer)
75 Mutex_Release(&Buffer->lBufferLock);
78 void IPStack_Buffer_AppendSubBuffer(tIPStackBuffer *Buffer,
79 size_t HeaderLen, size_t FooterLen, const void *Data,
80 tIPStackBufferCb Cb, void *Arg
83 if( Buffer->nSubBuffers == Buffer->MaxSubBufffers ) {
85 Log_Error("IPStack", "Buffer %p only had %i sub-buffers allocated, which was not enough",
86 Buffer, Buffer->MaxSubBufffers);
90 int index = Buffer->nSubBuffers++;
91 Buffer->TotalLength += HeaderLen + FooterLen;
93 Buffer->SubBuffers[index].Data = Data;
94 Buffer->SubBuffers[index].PreLength = HeaderLen;
95 Buffer->SubBuffers[index].PostLength = FooterLen;
96 Buffer->SubBuffers[index].Cb = Cb;
97 Buffer->SubBuffers[index].CbArg = Arg;
100 size_t IPStack_Buffer_GetLength(tIPStackBuffer *Buffer)
102 return Buffer->TotalLength;
105 size_t IPStack_Buffer_GetData(tIPStackBuffer *Buffer, void *Dest, size_t MaxBytes)
108 size_t rem_space = MaxBytes;
111 for( int i = Buffer->nSubBuffers; i -- && rem_space != 0; )
113 len = MIN(Buffer->SubBuffers[i].PreLength, rem_space);
115 Buffer->SubBuffers[i].Data,
121 for( int i = 0; i < Buffer->nSubBuffers && rem_space; i ++ )
123 if( Buffer->SubBuffers[i].PostLength == 0 )
126 len = MIN(Buffer->SubBuffers[i].PostLength, rem_space);
128 (Uint8*)Buffer->SubBuffers[i].Data + Buffer->SubBuffers[i].PreLength,
135 return MaxBytes - rem_space;
138 void *IPStack_Buffer_CompactBuffer(tIPStackBuffer *Buffer, size_t *Length)
142 ret = malloc(Buffer->TotalLength);
148 *Length = Buffer->TotalLength;
150 IPStack_Buffer_GetData(Buffer, ret, Buffer->TotalLength);
155 int IPStack_Buffer_GetBuffer(tIPStackBuffer *Buffer, int Index, size_t *Length, const void **DataPtr)
157 if( Index == -1 ) Index = 0;
159 if( Index >= Buffer->nSubBuffers*2 ) {
163 if( Index >= Buffer->nSubBuffers )
166 Index -= Buffer->nSubBuffers;
168 // Bit of a hack to avoid multiple calls which return a zero length
169 while( !Buffer->SubBuffers[Index].PostLength )
171 if( Index++ == Buffer->nSubBuffers )
175 *DataPtr = (Uint8*)Buffer->SubBuffers[Index].Data + Buffer->SubBuffers[Index].PreLength;
176 *Length = Buffer->SubBuffers[Index].PostLength;
178 return (Index + 1) + Buffer->nSubBuffers;
183 Index = Buffer->nSubBuffers - Index - 1;
185 *DataPtr = Buffer->SubBuffers[Index].Data;
186 *Length = Buffer->SubBuffers[Index].PreLength;