📄 irdatdi.c
字号:
if (pAddrObj == NULL)
{
DEBUGMSG(ZONE_ERROR, (TEXT("IRLMP_AssociateAddress(0x%X,0x%X) pAddrObj==NULL\r\n"), pTDIReq, (unsigned) AddrHandle));
TdiStatus = TDI_ADDR_INVALID;
goto done;
}
if (pConn == NULL)
{
DEBUGMSG(ZONE_ERROR, (TEXT("IRLMP_AssociateAddress(0x%X,0x%X) pConn==NULL\r\n"), pTDIReq, (unsigned) AddrHandle));
REFDELADDR(pAddrObj);
TdiStatus = TDI_INVALID_CONNECTION;
goto done;
}
VALIDCONN(pConn);
VALIDADDR(pAddrObj);
DEBUGMSG(ZONE_TDI,
(TEXT("Associate Addr:%#x, id:%d; Conn:%#x, id:%d\r\n"),
pAddrObj, pAddrObj->dwId, pConn, pConn->dwId));
EnterCriticalSection(&csIrObjList);
ASSERT(pConn->pAddrObj == NULL);
// Connection should be on unassociated list.
RemoveEntryList(&pConn->Linkage);
// Associate address and connection.
InsertHeadList(&pAddrObj->ConnList, (PLIST_ENTRY)pConn);
GET_CONN_LOCK(pConn);
memcpy(&pConn->SockAddrLocal, &pAddrObj->SockAddrLocal,
sizeof(SOCKADDR_IRDA));
pConn->IsServer = pAddrObj->IsServer;
pConn->LSAPSelLocal = pAddrObj->LSAPSelLocal;
pConn->UseExclusiveMode = pAddrObj->UseExclusiveMode;
pConn->UseIrLPTMode = pAddrObj->UseIrLPTMode;
pConn->Use9WireMode = pAddrObj->Use9WireMode;
pConn->UseSharpMode = pAddrObj->UseSharpMode;
// Link IRLMP_CONNECTION to IRLMP_ADDR_OBJ.
pConn->pAddrObj = pAddrObj;
FREE_CONN_LOCK(pConn);
LeaveCriticalSection(&csIrObjList);
// Keep reference to Address since we have pAddrObj in connection.
// But remove reference to connection.
REFDELCONN(pConn);
done:
DEBUGMSG(ZONE_FUNCTION,
(TEXT("-IRLMP_AssociateAddress [%#x (%d)]\r\n"), TdiStatus, TdiStatus));
return(TdiStatus);
}
/*****************************************************************************
*
* @func TDI_STATUS | IRLMP_DisAssociateAddress | NOT DONE
*/
TDI_STATUS
IRLMP_DisAssociateAddress(PTDI_REQUEST pTDIReq)
{
DEBUGMSG(ZONE_FUNCTION,
(TEXT("IRLMP_DisAssociateAddress(0x%X)\r\n"), pTDIReq));
ASSERT(0);
return(TDI_SUCCESS);
}
// Our own internal disassociate.
TDI_STATUS
TdiDisassociateAddress(PIRLMP_CONNECTION pConn)
{
PIRLMP_ADDR_OBJ pAddr;
EnterCriticalSection(&csIrObjList);
VALIDCONN(pConn);
if (pConn) {
// Remove from address list.
RemoveEntryList((PLIST_ENTRY)pConn);
// Add to unassociated connection list.
InsertHeadList(&IrConnObjList, (PLIST_ENTRY)pConn);
GET_CONN_LOCK(pConn);
pAddr = pConn->pAddrObj;
VALIDADDR(pAddr); // Shouldn't be NULL here.
pConn->pAddrObj = NULL;
FREE_CONN_LOCK(pConn);
REFDELADDR(pAddr);
}
LeaveCriticalSection(&csIrObjList);
return (TDI_SUCCESS);
}
/*****************************************************************************
*
* @func TDI_STATUS | IRLMP_Connect |
* Called after connect(). Initiates an IRLMP connection.
* IRLMP will call ConnectComplete() when the connection is
* established.
*
* @rdesc
* TDI_SUCCESS (tdistat.h) on success, or (tdistat.h)
* @errors
* @ecode TDI_PENDING | ConnectComplete() will be called.
*
* @parm PTDI_REQUEST | pTDIReq |
* (tdi.h) pTDIReq->Handle.ConnectionContext contains the
* CONNECTION_CONTEXT (tdi.h, PVOID) of the IRLMP_CONNECTION.
* IRLMP_OpenConnection() assigns this value to be a pointer to
* the IRLMP_CONNECTION.
* <nl>pTDIReq->RequestNotifyObject is a pointer (void (*)(PVOID
* Context, TDI_STATUS FinalStatus, unsigned long ByteCount)) to a
* Winsock routine to call if this function returns TDI_PENDING.
* <nl>pTDIReq->RequestNotifyContext is a Winsock context to return in
* the callback.
* @parm PVOID | pTimeOut |
* sockutil.c appears to always set this -1. IrLMP will ignore it.
* @parm PTDI_CONNECTION_INFORMATION | pReqAddr |
* Pointer to input TDI_CONNECTION_INFORMATION (tdi.h) struct.
* IrLMP assumes RemoteAddress points to a TRANSPORT_ADDRESS (tdi.h)
* struct. IrLMP assumes one TA_ADDRESS entry with the Address field
* containing the remaining bytes of a SOCKADDR_IRDA struct minus the
* first two bytes.
* @parm PTDI_CONNECTION_INFORMATION | pRetAddr |
* Pointer to output TDI_CONNECTION_INFORMATION (tdi.h) struct.
*
* @xref <f ConnectComplete>
*/
TDI_STATUS
IRLMP_Connect(PTDI_REQUEST pTDIReq,
PVOID pTimeOut,
PTDI_CONNECTION_INFORMATION pReqAddr,
PTDI_CONNECTION_INFORMATION pRetAddr)
{
TDI_STATUS TdiStatus = TDI_PENDING;
PIRLMP_CONNECTION pConn;
IRDA_MSG IrDAMsg;
int rc;
int i;
int RetryCount = 0;
int IrlptMode = 1;
DWORD dwTemp; // For compiler
BOOL bLPTMode;
DWORD dwAddr;
BYTE ServiceName[25];
DWORD dwLSAPSelRemote;
DEBUGMSG(ZONE_FUNCTION,
(TEXT("+IRLMP_Connect(0x%X,0x%X,0x%X,0x%X)\r\n"),
pTDIReq, pTimeOut, pReqAddr, pRetAddr));
pConn = GETCONN(pTDIReq->Handle.ConnectionContext);
if (pConn == NULL)
{
TdiStatus = TDI_INVALID_CONNECTION;
goto done_nolocks;
}
GET_CONN_LOCK(pConn);
if (pConn->IsServer)
{
TdiStatus = TDI_INVALID_REQUEST;
goto ExitIRLMP_Connect;
}
memcpy(&pConn->SockAddrRemote,
(BYTE *) &((PTRANSPORT_ADDRESS)
pReqAddr->RemoteAddress)->Address[0].AddressType,
sizeof(SOCKADDR_IRDA));
pConn->pConnectComplete = pTDIReq->RequestNotifyObject;
pConn->pConnectCompleteContext = NULL;
pConn->ConnState = IRLMP_CONN_OPENING;
pConn->fConnPending = FALSE;
EnterCriticalSection(&csIasQuery);
if (memcmp(&pConn->SockAddrRemote.irdaServiceName[0], LSAPSEL_TXT, LSAPSEL_TXTLEN) == 0)
{
pConn->LSAPSelRemote = ParseLsapSel(
&pConn->SockAddrRemote.irdaServiceName[LSAPSEL_TXTLEN]);
LeaveCriticalSection(&csIasQuery);
if (pConn->LSAPSelRemote == -1)
{
TdiStatus = TDI_ADDR_INVALID;
goto ExitIRLMP_Connect;
}
}
else
{
LeaveCriticalSection(&csIasQuery);
//
// Let go of the connection during the query and reacquire it later.
//
memcpy(&dwAddr, &pConn->SockAddrRemote.irdaDeviceID, IRDA_DEV_ADDR_LEN);
memcpy(ServiceName, pConn->SockAddrRemote.irdaServiceName, 25);
bLPTMode = pConn->UseIrLPTMode;
FREE_CONN_LOCK(pConn);
REFDELCONN(pConn);
pConn = NULL;
EnterCriticalSection(&csIasQuery);
RetryIASQuery:
if (IASQueryInProgress)
{
DEBUGMSG (ZONE_ERROR,
(TEXT("TDI:IRLMP_Connect returning TDI_IN_PROGRESS ")
TEXT("because IASQueryInProgress\r\n")));
TdiStatus = TDI_IN_PROGRESS;
goto ExitIRLMP_Connect_IASQuery;
}
// If we've been going around too many times then give up
if (RetryCount++ > 20) {
DEBUGMSG (ZONE_ERROR,
(TEXT("TDI:IRLMP_Connect returning TDI_NET_DOWN ")
TEXT("because too many retries of IAS Query\r\n")));
TdiStatus = TDI_NET_DOWN;
goto ExitIRLMP_Connect_IASQuery;
}
IASQueryInProgress = TRUE;
pIASQuery = &ConnectIASQuery;
IrDAMsg.Prim = IRLMP_GETVALUEBYCLASS_REQ;
IrDAMsg.IRDA_MSG_pIasQuery = pIASQuery;
IrDAMsg.IRDA_MSG_AttribLen = 1;
memcpy(&pIASQuery->irdaDeviceID[0], &dwAddr, IRDA_DEV_ADDR_LEN);
i = 0;
// sh - Only allow 24 chars. We truncate the name because we
// have doc'd that it must be a NULL-terminated string
// in a 25 char array.
while (ServiceName[i] && i < 24)
{
pIASQuery->irdaClassName[i] = ServiceName[i];
i++;
}
pIASQuery->irdaClassName[i] = 0;
if (bLPTMode)
{
// Two different attribute names for printers...most common
// is IrDA:IrLMP:LsapSel.
if (IrlptMode == 1)
{
strcpy(pIASQuery->irdaAttribName, "IrDA:IrLMP:LsapSel");
}
else
{
ASSERT(IrlptMode == 2);
strcpy(pIASQuery->irdaAttribName, "IrDA:IrLMP:LSAPSel");
}
}
else
{
strcpy(pIASQuery->irdaAttribName, IasAttribName_TTPLsapSel);
}
LeaveCriticalSection(&csIasQuery);
rc = IrlmpDown(NULL, &IrDAMsg);
if (rc != 0)
{
EnterCriticalSection(&csIasQuery);
IASQueryInProgress = FALSE;
LeaveCriticalSection(&csIasQuery);
if (rc == IRLMP_LINK_IN_USE)
{
TdiStatus = TDI_ADDR_IN_USE;
}
else if (rc == IRLMP_BAD_DEV_ADDR)
{
DEBUGMSG(ZONE_ERROR,
(TEXT("IrLMP: Can't connect - invalid address\r\n")));
TdiStatus = TDI_ADDR_INVALID;
}
else
{
ERRORMSG(1,
(TEXT("IrLMP: unrecoverable error %d\r\n"), rc));
TdiStatus = WSANO_RECOVERY;
}
goto done_nolocks;
}
// We might get an IRLMP_IRLAP_REMOTE_DISCOVERY_IN_PROGRESS error
// which means we want to wait until the discovery is complete.
// We need to do this here to ensure that we don't miss the
// Discovery Indication as we enter and leave the critical section
ResetEvent(DscvIndEvent);
WaitForSingleObject(IASQueryConfEvent, INFINITE);
EnterCriticalSection(&csIasQuery);
IASQueryInProgress = FALSE;
if (IASQueryStatus == IRLMP_IAS_SUCCESS)
{
dwLSAPSelRemote = pIASQuery->irdaAttribute.irdaAttribInt;
if (dwLSAPSelRemote > HIGHEST_LSAP_SEL)
{
TdiStatus = TDI_BAD_ADDR;
goto ExitIRLMP_Connect_IASQuery;
}
LeaveCriticalSection(&csIasQuery);
}
else
{
switch(IASQueryStatus)
{
case IRLMP_MAC_MEDIA_BUSY:
DEBUGMSG (1, (TEXT("GOT IRLMP_MAC_MEDIA_BUSY in TDI:IRLMPConnect, retrying query\r\n")));
*(volatile DWORD*)&dwTemp = 0; // This avoids an SH3 compiler (#14740).
goto RetryIASQuery;
break;
case IRLMP_IRLAP_REMOTE_DISCOVERY_IN_PROGRESS:
/* wmz retry the query after DISCOVERY_IND */
DEBUGMSG (1, (TEXT("GOT IRLMP_IRLAP_REMOTE_DISCOVERY_IN_PROGRESS in TDI:IRLMPConnect\r\n")));
LeaveCriticalSection(&csIasQuery);
WaitForSingleObject (DscvIndEvent, INFINITE);
EnterCriticalSection(&csIasQuery);
DEBUGMSG (1, (TEXT("GOT IRLMP_IRLAP_REMOTE_DISCOVERY_IN_PROGRESS in TDI:IRLMPConnect\r\n")));
goto RetryIASQuery;
break;
case IRLMP_DISC_LSAP:
TdiStatus = TDI_CONN_REFUSED;
break;
case IRLMP_NO_RESPONSE_LSAP:
TdiStatus = TDI_TIMED_OUT;
break;
case IRLMP_IAS_NO_SUCH_OBJECT:
TdiStatus = TDI_CONN_REFUSED;
break;
case IRLMP_IAS_NO_SUCH_ATTRIB:
// This will retry the different Irlpt printer attribute names.
if (IrlptMode == 1)
{
IrlptMode++;
goto RetryIASQuery;
}
TdiStatus = TDI_CONN_REFUSED;
break;
default:
TdiStatus = TDI_CONNECTION_ABORTED;
break;
}
goto ExitIRLMP_Connect_IASQuery;
}
}
if (pConn == NULL) {
//
// Reacquire conn after query
//
pConn = GETCONN(pTDIReq->Handle.ConnectionContext);
if (pConn == NULL) {
DEBUGMSG(ZONE_WARN, (TEXT("IRLMP_Connect - connection 0x%X gone after query\r\n"), pTDIReq->Handle.ConnectionContext));
TdiStatus = TDI_CONNECTION_ABORTED;
goto done_nolocks;
}
GET_CONN_LOCK(pConn);
pConn->LSAPSelRemote = dwLSAPSelRemote;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -