home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Network Support Encyclopedia 96-1
/
novell-nsepro-1996-1-cd2.iso
/
download
/
netware
/
dax1.exe
/
DAP
/
DAPE
/
DAPSEND.C
< prev
next >
Wrap
Text File
|
1992-07-15
|
10KB
|
237 lines
// ╔════════════════════════════════════════════════════════════════════╗
// ║ ║
// ║ module: dapsend.c ║
// ║ abstract: This module contains the send logic for the engine. ║
// ║ ║
// ║ environment: NetWare 3.x v3.11 ║
// ║ Network C for NLMs SDK ║
// ║ CLib v3.11 ║
// ║ ║
// ║ This software is provided as is and carries no warranty ║
// ║ whatsoever. Novell disclaims and excludes any and all implied ║
// ║ warranties of merchantability, title and fitness for a particular ║
// ║ purpose. Novell does not warrant that the software will satisfy ║
// ║ your requirements or that the software is without defect or error ║
// ║ or that operation of the software will be uninterrupted. You are ║
// ║ using the software at your risk. The software is not a product ║
// ║ of Novell, Inc. or any of subsidiaries. ║
// ║ ║
// ╟────────────────────────────────────────────────────────────────────╢
// ║ maintenance history: ║
// ║ level date pi description ║
// ╟────────────────────────────────────────────────────────────────────╢
// ║ 001 03/03/92 kl initial release. ║
// ╚════════════════════════════════════════════════════════════════════╝
#include <stdio.h>
#include <process.h>
#include <nwsemaph.h>
#include <library.h>
#include <errno.h>
#include "cp/cpapi.h"
#include "dap/dapsys.h"
STATIC DAPDATA *queueHead;
STATIC LONG sendSema;
STATIC LONG sendThreadID;
//
// Link the structure onto the reply queue. Signal the semaphore
// to wake up the Service Reply Queue thread.
//
// This queue is ordered just like the Ipx queueHead implementation
// in CLib. See NLM Reference Volume 1 for a complete description
// of queue Head pointers.
//
// This API is called by the individual protocol routines to enqueue
// a reply to a client.
//
void DAPEnqueueServiceReply(DAPDATA *DAPid)
{
char *error = "EnqueueServiceReply called with %sactive DAPid (%x)\n";
//
// Make sure the DAPid is in use, and that the state is DAP_SERVICE
//
DIAG4("EREP: validate DAPid");
if(!DAPInUse(DAPid)){
xDIAG1(DAPprintf(error, "in", DAPid));
return;
}
else if(!DAPStateActive(DAPid,DAP_SERVICE)){
DIAG1("EREP: called with bad state");
return;
}
//
// Link this one onto the linked list.
//
DIAG4("EREP: linking DAPid onto list");
if( DAPid->next = queueHead ){
DAPid->prev = DAPid->next->prev;
DAPid->next->prev = DAPid;
}
else{
DAPid->prev = DAPid;
}
queueHead = DAPid;
//
// Set state to 'sitting on the send queue'.
//
DAPStateON(DAPid,DAP_SENDQUEUE);
//
// Tell the service thread "there's work to-be-done!"
//
DIAG4("EREP: waking up service reply queue thread");
if( sendSema ) SignalLocalSemaphore(sendSema);
}
//
// This is the thread which services the reply queue. It sends the
// reply via CPSendMessage, and then delinks the structure from the reply
// queue.
//
STATIC void DAPServiceReplyQueue(void *threadID)
{
int rc;
DAPDATA *queuedDAPid;
DAPDATA *currDAPid, *nextDAPid;
#define SuspendOrStop() if(!sendSema){*(LONG *)threadID = 0;ExitThread(EXIT_THREAD,0);}
*(LONG *)threadID = GetThreadID();
xDIAG1(RenameThread(GetThreadID(),"DAP_SREP"));
while( 1 ){
//
// Wait for DAPid(s) to be posted to the queueHead
//
SuspendOrStop();
WaitOnLocalSemaphore(sendSema);
SuspendOrStop();
//
// Since we can handle multiple requests in the loop below,
// we might wake up from the semaphore without any work todo.
// If this is the case, just wait again...
//
if( !queueHead ) continue;
//
// Get and clear the queue head pointer.
//
nextDAPid = (queuedDAPid = queueHead)->prev, queueHead = NULL;
do{
//
// Process the newly received request
//
DAPStateON( currDAPid = nextDAPid, DAP_SENDING );
DAPStateOFF(currDAPid,DAP_SENDQUEUE);
//
// Traverse the linked list backwards, in the order they
// were queued by DAPEnqueueServiceReply().
//
nextDAPid = currDAPid->prev;
//
// Make final preparation to the dapReply structure.
//
currDAPid->dapReply.packetType = DAPSERVICEREPLY;
currDAPid->dapReply.sequence = currDAPid->dapRequest.sequence;
//
// Send the reply to the client
//
if( rc = CPSendMessage(currDAPid->CPid,
&currDAPid->dapReply,
sizeof currDAPid->dapReply) ){
DAPprintf("Error sending message: %x\n",currDAPid->CPid);
xDIAG2(DAPprintf("CPSendMessage returned: %04x\n",rc));
}
else{
xDIAG4(DAPprintf("Successful send to DAPid (%x)\n",currDAPid));
}
SuspendOrStop();
//
// Show we are no longer sending
//
DAPStateOFF( currDAPid, DAP_SENDING );
//
// Check to see if we need to release this structure.
// This flag is normally set on DAPDeAllocateSession()
// to tell me that I can free the entry after sending
// this final reply.
//
//!!
// Seems like we need to just save the CPSession index
// instead of a pointer.
//!!
// Maybe combine the DAPFlags with DAPState...
// Try a test where the client tries to logout twice...
//!!
if( DAPFlagIsSet(currDAPid,DAP_FREE_THIS_SLOT) ) {
//
// Tell the CP Layer to clear this client's session id
//
CPClearSessionID(currDAPid->CPid);
//
// Release this structure back to free pool
// DAPDeAllocateSlot() doesn't care about the state
// of the session, other than if it is an allocated
// slot...
//
DAPDeAllocateSlot(currDAPid);
xDIAG3(DAPprintf("DeAllocated DAPid (%x)\n", currDAPid));
}
else{
//
// Mark this DAP structure as ready to use
//
currDAPid->next = currDAPid->prev = NULL;
//
// By turning off the INUSE state, we allow the
// receiving thread to post a new request to this
// client structure.
//
// This state set on in the EnqueueServiceRequest API
//
DAPStateOFF( currDAPid, DAP_INUSE );
}
ThreadSwitch();
SuspendOrStop();
//
// When currDAPid == queuedDAPid, we have reached the end of
// the linked list. Loop back and wait for another message.
//
}while( currDAPid != queuedDAPid ); // until end of list
}
}
T_RC DAPInitializeSendLogic()
{
//
// We need a local semaphore to block the service thread
//
if( (sendSema = OpenLocalSemaphore(0)) == -1){
sendSema = 0; // so we don't accidentally close it
DIAG4("Could not open DAP sending semaphore");
return DAP_RESOURCE_ERROR;
}
if( BeginThread(DAPServiceReplyQueue,NULL,8192,&sendThreadID) == EFAILURE ){
DIAG4("Could not start ServiceReplyQueue thread");
return DAP_RESOURCE_ERROR;
}
ThreadSwitch(); // let the thread run once...
DIAG4("DAP Send Logic has been initialized");
return DAP_SUCCESS;
}
void DAPDeInitializeSendLogic()
{
//
// Most of the time, this API will be called during atexit()
// processing.
//
if( sendSema ){
CloseLocalSemaphore(sendSema);
sendSema = 0; // signal thread to shut down ...
}
DIAG4("DAP Send Logic has been DE-initialized");
}