X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FModules%2FIPStack%2Fbuffer.c;h=b3c8093ee24f9de51dc8df28f2021bf134d6513a;hb=326d03e0dc49158f24ab14c92b7245d860ecf7ed;hp=9151c1c1a20b9104941b19ead440f4671bbf4c91;hpb=849329d50395b44ac97c5b5145fc2df0749eace2;p=tpg%2Facess2.git diff --git a/KernelLand/Modules/IPStack/buffer.c b/KernelLand/Modules/IPStack/buffer.c index 9151c1c1..b3c8093e 100644 --- a/KernelLand/Modules/IPStack/buffer.c +++ b/KernelLand/Modules/IPStack/buffer.c @@ -14,11 +14,15 @@ struct sIPStackBuffer int MaxSubBufffers; int nSubBuffers; size_t TotalLength; + tMutex lBufferLock; + struct _subbuffer { const void *Data; size_t PreLength; size_t PostLength; + tIPStackBufferCb Cb; + void *CbArg; // TODO: Callbacks? } SubBuffers[]; }; @@ -29,26 +33,59 @@ tIPStackBuffer *IPStack_Buffer_CreateBuffer(int MaxBuffers) tIPStackBuffer *ret; ret = malloc( sizeof(*ret) + MaxBuffers * sizeof(ret->SubBuffers[0]) ); + ASSERTR(ret, NULL); ret->MaxSubBufffers = MaxBuffers; ret->nSubBuffers = 0; ret->TotalLength = 0; + memset(&ret->lBufferLock, 0, sizeof(ret->lBufferLock)); memset(ret->SubBuffers, 0, MaxBuffers * sizeof(ret->SubBuffers[0])); return ret; } +void IPStack_Buffer_ClearBuffer(tIPStackBuffer *Buffer) +{ + ASSERT(Buffer); + IPStack_Buffer_LockBuffer(Buffer); + for( int i = 0; i < Buffer->nSubBuffers; i ++ ) + { + if( Buffer->SubBuffers[i].Cb == NULL ) + continue ; + Buffer->SubBuffers[i].Cb( + Buffer->SubBuffers[i].CbArg, + Buffer->SubBuffers[i].PreLength, + Buffer->SubBuffers[i].PostLength, + Buffer->SubBuffers[i].Data + ); + } + Buffer->nSubBuffers = 0; + IPStack_Buffer_UnlockBuffer(Buffer); +} + void IPStack_Buffer_DestroyBuffer(tIPStackBuffer *Buffer) { - // TODO: Fire callbacks? + ASSERT(Buffer); + IPStack_Buffer_ClearBuffer(Buffer); Buffer->MaxSubBufffers = 0; - Buffer->nSubBuffers = 0; free(Buffer); } +void IPStack_Buffer_LockBuffer(tIPStackBuffer *Buffer) +{ + ASSERT(Buffer); + Mutex_Acquire(&Buffer->lBufferLock); +} +void IPStack_Buffer_UnlockBuffer(tIPStackBuffer *Buffer) +{ + ASSERT(Buffer); + Mutex_Release(&Buffer->lBufferLock); +} + void IPStack_Buffer_AppendSubBuffer(tIPStackBuffer *Buffer, size_t HeaderLen, size_t FooterLen, const void *Data, tIPStackBufferCb Cb, void *Arg ) { + ASSERT(Buffer); if( Buffer->nSubBuffers == Buffer->MaxSubBufffers ) { // Ah, oops? Log_Error("IPStack", "Buffer %p only had %i sub-buffers allocated, which was not enough", @@ -62,56 +99,76 @@ void IPStack_Buffer_AppendSubBuffer(tIPStackBuffer *Buffer, Buffer->SubBuffers[index].Data = Data; Buffer->SubBuffers[index].PreLength = HeaderLen; Buffer->SubBuffers[index].PostLength = FooterLen; + Buffer->SubBuffers[index].Cb = Cb; + Buffer->SubBuffers[index].CbArg = Arg; } size_t IPStack_Buffer_GetLength(tIPStackBuffer *Buffer) { + ASSERT(Buffer); return Buffer->TotalLength; } -void *IPStack_Buffer_CompactBuffer(tIPStackBuffer *Buffer, size_t *Length) +size_t IPStack_Buffer_GetData(tIPStackBuffer *Buffer, void *Dest, size_t MaxBytes) { - void *ret; - ret = malloc(Buffer->TotalLength); - if(!ret) { - *Length = 0; - return NULL; - } + ASSERT(Buffer); + Uint8 *dest = Dest; + size_t rem_space = MaxBytes; + size_t len; - *Length = Buffer->TotalLength; - - Uint8 *dest = ret; - for( int i = Buffer->nSubBuffers; i --; ) + for( int i = Buffer->nSubBuffers; i -- && rem_space != 0; ) { + len = MIN(Buffer->SubBuffers[i].PreLength, rem_space); memcpy(dest, Buffer->SubBuffers[i].Data, - Buffer->SubBuffers[i].PreLength + len ); - dest += Buffer->SubBuffers[i].PreLength; + dest += len; + rem_space -= len; } - for( int i = 0; i < Buffer->nSubBuffers; i ++ ) + for( int i = 0; i < Buffer->nSubBuffers && rem_space; i ++ ) { - if( Buffer->SubBuffers[i].PostLength ) - { - memcpy(dest, - (Uint8*)Buffer->SubBuffers[i].Data + Buffer->SubBuffers[i].PreLength, - Buffer->SubBuffers[i].PostLength - ); - dest += Buffer->SubBuffers[i].PreLength; - } + if( Buffer->SubBuffers[i].PostLength == 0 ) + continue ; + + len = MIN(Buffer->SubBuffers[i].PostLength, rem_space); + memcpy(dest, + (Uint8*)Buffer->SubBuffers[i].Data + Buffer->SubBuffers[i].PreLength, + len + ); + dest += len; + rem_space -= len; + } + + return MaxBytes - rem_space; +} + +void *IPStack_Buffer_CompactBuffer(tIPStackBuffer *Buffer, size_t *Length) +{ + ASSERT(Buffer); + void *ret = malloc(Buffer->TotalLength); + if(!ret) { + *Length = 0; + return NULL; } + + *Length = Buffer->TotalLength; + + IPStack_Buffer_GetData(Buffer, ret, Buffer->TotalLength); + return ret; } int IPStack_Buffer_GetBuffer(tIPStackBuffer *Buffer, int Index, size_t *Length, const void **DataPtr) { + ASSERT(Buffer); if( Index == -1 ) Index = 0; if( Index >= Buffer->nSubBuffers*2 ) { return -1; } - if( Index > Buffer->nSubBuffers ) + if( Index >= Buffer->nSubBuffers ) { // Appended buffers Index -= Buffer->nSubBuffers; @@ -123,18 +180,23 @@ int IPStack_Buffer_GetBuffer(tIPStackBuffer *Buffer, int Index, size_t *Length, return -1; } - *DataPtr = (Uint8*)Buffer->SubBuffers[Index].Data + Buffer->SubBuffers[Index].PreLength; - *Length = Buffer->SubBuffers[Index].PostLength; + if( DataPtr ) + *DataPtr = (Uint8*)Buffer->SubBuffers[Index].Data + Buffer->SubBuffers[Index].PreLength; + if( Length ) + *Length = Buffer->SubBuffers[Index].PostLength; return (Index + 1) + Buffer->nSubBuffers; } else { - Index = Buffer->nSubBuffers - Index; + int rv = Index + 1; + Index = Buffer->nSubBuffers - Index - 1; // Prepended buffers - *DataPtr = Buffer->SubBuffers[Index].Data; - *Length = Buffer->SubBuffers[Index].PreLength; - return Buffer->nSubBuffers - (Index - 1); + if( DataPtr ) + *DataPtr = Buffer->SubBuffers[Index].Data; + if( Length ) + *Length = Buffer->SubBuffers[Index].PreLength; + return rv; } }