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 if( !CheckMem(Buffer->SubBuffers[i].Data, len) ) {
124 Log_Error("IPStack", "Buffer pre %i invalid (%p+0x%x)",
125 i, Buffer->SubBuffers[i].Data, len);
130 Buffer->SubBuffers[i].Data,
136 for( int i = 0; i < Buffer->nSubBuffers && rem_space; i ++ )
138 if( Buffer->SubBuffers[i].PostLength == 0 )
141 len = MIN(Buffer->SubBuffers[i].PostLength, rem_space);
142 void *ptr = (Uint8*)Buffer->SubBuffers[i].Data + Buffer->SubBuffers[i].PreLength;
143 ASSERT( CheckMem(ptr, len) );
144 memcpy(dest, ptr, len);
149 return MaxBytes - rem_space;
152 void *IPStack_Buffer_CompactBuffer(tIPStackBuffer *Buffer, size_t *Length)
155 void *ret = malloc(Buffer->TotalLength);
161 *Length = Buffer->TotalLength;
163 IPStack_Buffer_GetData(Buffer, ret, Buffer->TotalLength);
168 int IPStack_Buffer_GetBuffer(tIPStackBuffer *Buffer, int Index, size_t *Length, const void **DataPtr)
171 if( Index == -1 ) Index = 0;
173 if( Index >= Buffer->nSubBuffers*2 ) {
177 if( Index >= Buffer->nSubBuffers )
180 Index -= Buffer->nSubBuffers;
182 // Bit of a hack to avoid multiple calls which return a zero length
183 while( !Buffer->SubBuffers[Index].PostLength )
185 if( Index++ == Buffer->nSubBuffers )
190 *DataPtr = (Uint8*)Buffer->SubBuffers[Index].Data + Buffer->SubBuffers[Index].PreLength;
192 *Length = Buffer->SubBuffers[Index].PostLength;
194 return (Index + 1) + Buffer->nSubBuffers;
199 Index = Buffer->nSubBuffers - Index - 1;
202 *DataPtr = Buffer->SubBuffers[Index].Data;
204 *Length = Buffer->SubBuffers[Index].PreLength;