2 * Acess2 Networking Stack
3 * - By John Hodge (thePowersGang)
6 * - Scatter-gather handling
10 #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)
66 LOG("Called with %p by %p", Buffer, __builtin_return_address(0));
68 IPStack_Buffer_ClearBuffer(Buffer);
69 Buffer->MaxSubBufffers = 0;
73 void IPStack_Buffer_LockBuffer(tIPStackBuffer *Buffer)
76 Mutex_Acquire(&Buffer->lBufferLock);
78 void IPStack_Buffer_UnlockBuffer(tIPStackBuffer *Buffer)
81 Mutex_Release(&Buffer->lBufferLock);
84 void IPStack_Buffer_AppendSubBuffer(tIPStackBuffer *Buffer,
85 size_t HeaderLen, size_t FooterLen, const void *Data,
86 tIPStackBufferCb Cb, void *Arg
90 if( Buffer->nSubBuffers == Buffer->MaxSubBufffers ) {
92 Log_Error("IPStack", "Buffer %p only had %i sub-buffers allocated, which was not enough",
93 Buffer, Buffer->MaxSubBufffers);
97 int index = Buffer->nSubBuffers++;
98 Buffer->TotalLength += HeaderLen + FooterLen;
100 Buffer->SubBuffers[index].Data = Data;
101 Buffer->SubBuffers[index].PreLength = HeaderLen;
102 Buffer->SubBuffers[index].PostLength = FooterLen;
103 Buffer->SubBuffers[index].Cb = Cb;
104 Buffer->SubBuffers[index].CbArg = Arg;
107 size_t IPStack_Buffer_GetLength(tIPStackBuffer *Buffer)
110 return Buffer->TotalLength;
113 size_t IPStack_Buffer_GetData(tIPStackBuffer *Buffer, void *Dest, size_t MaxBytes)
117 size_t rem_space = MaxBytes;
120 for( int i = Buffer->nSubBuffers; i -- && rem_space != 0; )
122 len = MIN(Buffer->SubBuffers[i].PreLength, rem_space);
124 if( !CheckMem(Buffer->SubBuffers[i].Data, len) ) {
125 Log_Error("IPStack", "Buffer pre %i invalid (%p+0x%x)",
126 i, Buffer->SubBuffers[i].Data, len);
131 Buffer->SubBuffers[i].Data,
137 for( int i = 0; i < Buffer->nSubBuffers && rem_space; i ++ )
139 if( Buffer->SubBuffers[i].PostLength == 0 )
142 len = MIN(Buffer->SubBuffers[i].PostLength, rem_space);
143 void *ptr = (Uint8*)Buffer->SubBuffers[i].Data + Buffer->SubBuffers[i].PreLength;
144 ASSERT( CheckMem(ptr, len) );
145 memcpy(dest, ptr, len);
150 return MaxBytes - rem_space;
153 void *IPStack_Buffer_CompactBuffer(tIPStackBuffer *Buffer, size_t *Length)
156 void *ret = malloc(Buffer->TotalLength);
162 *Length = Buffer->TotalLength;
164 IPStack_Buffer_GetData(Buffer, ret, Buffer->TotalLength);
169 int IPStack_Buffer_GetBuffer(tIPStackBuffer *Buffer, int Index, size_t *Length, const void **DataPtr)
172 if( Index == -1 ) Index = 0;
174 if( Index >= Buffer->nSubBuffers*2 ) {
178 if( Index >= Buffer->nSubBuffers )
181 Index -= Buffer->nSubBuffers;
183 // Bit of a hack to avoid multiple calls which return a zero length
184 while( !Buffer->SubBuffers[Index].PostLength )
186 if( Index++ == Buffer->nSubBuffers )
191 *DataPtr = (Uint8*)Buffer->SubBuffers[Index].Data + Buffer->SubBuffers[Index].PreLength;
193 *Length = Buffer->SubBuffers[Index].PostLength;
195 return (Index + 1) + Buffer->nSubBuffers;
200 Index = Buffer->nSubBuffers - Index - 1;
203 *DataPtr = Buffer->SubBuffers[Index].Data;
205 *Length = Buffer->SubBuffers[Index].PreLength;