/*++

Copyright (c) 1994  Microsoft Corporation

Module Name:

    buffer.h

Abstract:

    Contains manifests, macros, types and typedefs for buffer.c

Author:

    Richard L Firth (rfirth) 31-Oct-1994

Revision History:

    31-Oct-1994 rfirth
        Created

--*/

#if defined(__cplusplus)
extern "C" {
#endif

//
// manifests
//

//
// LOOK_AHEAD_LENGTH - read enough characters to comprise the maximum (32-bit)
// length returned by gopher+
//

#define LOOK_AHEAD_LENGTH   sizeof("+4294967296\r\n")   // 12

//
// BUFFER_INFO - structure maintains information about responses from gopher
// server. The same data can be shared amongst many requests
//

typedef struct {

    //
    // ReferenceCount - number of VIEW_INFO structures referencing this buffer
    //

    LONG ReferenceCount;

    //
    // Flags - information about the buffer
    //

    DWORD Flags;

    //
    // RequestEvent - the owner of this event is the only thread which can
    // make the gopher request that creates this buffer info. All other
    // requesters for the same information wait for the first thread to signal
    // the event, then just read the data returned by the first thread
    //

//    HANDLE RequestEvent;

    //
    // RequestWaiters - used in conjunction with RequestEvent. If this field
    // is 0 by the time the initial requester thread comes to signal the
    // event, it can do away with the event altogether, since it was only
    // required to stop those other threads from making a redundant request
    //

//    DWORD RequestWaiters;

    //
    // ConnectedSocket - contains socket we are using to receive the data in
    // the buffer, and the index into the parent SESSION_INFO's
    // ADDRESS_INFO_LIST of the address used to connect the socket
    //

//    CONNECTED_SOCKET ConnectedSocket;
    ICSocket * Socket;

    //
    // ResponseLength - the response length as told to us by the gopher+ server
    //

    int ResponseLength;

    //
    // BufferLength - length of Buffer
    //

    DWORD BufferLength;

    //
    // Buffer - containing response
    //

    LPBYTE Buffer;

    //
    // ResponseInfo - we read the gopher+ header information (i.e. length) here.
    // The main reason is so that we can determine the length of a gopher+ file
    // even though we were given a zero-length user buffer
    //

    char ResponseInfo[LOOK_AHEAD_LENGTH];

    //
    // BytesRemaining - number of bytes left in ResponseInfo that are data
    //

    int BytesRemaining;

    //
    // DataBytes - pointer into ResponseInfo where data bytes start
    //

    LPBYTE DataBytes;

    //
    // CriticalSection - used to serialize readers
    //

//    CRITICAL_SECTION CriticalSection;

} BUFFER_INFO, *LPBUFFER_INFO;

//
// BUFFER_INFO flags
//

#define BI_RECEIVE_COMPLETE 0x00000001  // receiver thread has finished
#define BI_DOT_AT_END       0x00000002  // buffer terminated with ".\r\n"
#define BI_BUFFER_RESPONSE  0x00000004  // response is buffered internally
#define BI_ERROR_RESPONSE   0x00000008  // the server responded with an error
#define BI_MOVEABLE         0x00000010  // buffer is moveable memory
#define BI_FIRST_RECEIVE    0x00000020  // this is the first receive
#define BI_OWN_BUFFER       0x00000040  // set if we own the buffer (directory)

//
// external data
//

DEBUG_DATA_EXTERN(LONG, NumberOfBuffers);

//
// prototypes
//

LPBUFFER_INFO
CreateBuffer(
    OUT LPDWORD Error
    );

VOID
DestroyBuffer(
    IN LPBUFFER_INFO BufferInfo
    );

VOID
AcquireBufferLock(
    IN LPBUFFER_INFO BufferInfo
    );

VOID
ReleaseBufferLock(
    IN LPBUFFER_INFO BufferInfo
    );

VOID
ReferenceBuffer(
    IN LPBUFFER_INFO BufferInfo
    );

LPBUFFER_INFO
DereferenceBuffer(
    IN LPBUFFER_INFO BufferInfo
    );

//
// macros
//

#if INET_DEBUG

#define BUFFER_CREATED()    ++NumberOfBuffers
#define BUFFER_DESTROYED()  --NumberOfBuffers
#define ASSERT_NO_BUFFERS() \
    if (NumberOfBuffers != 0) { \
        INET_ASSERT(FALSE); \
    }

#else

#define BUFFER_CREATED()    /* NOTHING */
#define BUFFER_DESTROYED()  /* NOTHING */
#define ASSERT_NO_BUFFERS() /* NOTHING */

#endif

#if defined(__cplusplus)
}
#endif