typedef struct _IAS_QUERY
{
u_char irdaDeviceID[4];
char irdaClassName[61];
char irdaAttribName[61];
u_short irdaAttribType;
union
{
int irdaAttribInt;
struct
{
int Len;
u_char OctetSeq[1];
u_char Reserved[3];
} irdaAttribOctetSeq;
struct
{
int Len;
u_char CharSet;
u_char UsrStr[1];
u_char Reserved[2];
} irdaAttribUsrStr;
} irdaAttribute;
} IAS_QUERY, *PIAS_QUERY, FAR *LPIAS_QUERY;
Figure 14 build_protocol_list
void build_protocol_list(string &new_list)
{
new_list="";
// initialize the transport protocol data structure
WSAPROTOCOL_INFO spi;
unsigned long size=sizeof(spi);
// query WinSock for the number of protocols
int num=WSAEnumProtocols(0,&spi,&size);
if (num==SOCKET_ERROR)
{
// allocate enough space for all the data structures
char *buf=new char[size];
WSAPROTOCOL_INFO *pi=(WSAPROTOCOL_INFO*)buf;
// start the actual enumeration
num=WSAEnumProtocols(0,pi,&size);
for (int i=0;i<num;i++)
{
// the szProtocol Field is not Unicode, convert it
TCHAR wdesc[300];
wsprintf(wdesc,
TEXT("%d;%s\n"),
(pi+i)->iAddressFamily,
(pi+i)->szProtocol);
// must convert back to non-Unicode for append
char desc[sizeof(wdesc)];
wcstombs(desc,wdesc,wcslen(wdesc)+1);
new_list+=desc;
}
delete [] buf;
}
}
Figure 15 get_irda_family_id
int get_irda_family_id(string &protocol_list)
{
// default return value
int family=-1;
// look for the id of this service provider
const char targetServiceProvider[]="MSAFD Irda [IrDA]";
const char *pstr=protocol_list.c_str();
while (*pstr && family==-1)
{
// identify end of current item
char *pendstr=strchr(pstr,'\n');
*pendstr=0;
// find and remove ';'
char *ptr=strchr(pstr,';');
*ptr=0;
// compare
if (!strcmp(ptr+1,targetServiceProvider))
{
// found it!
family=atoi(pstr);
}
// restore string
*ptr=';';
*pendstr='\n';
// bump to next string
pstr=pendstr+1;
}
return family;
}
Figure 16 Calling the Connect Function
// open a socket
SOCKET sock=socket(AF_IRDA,SOCK_STREAM,0);
if (SOCKET_ERROR!=sock)
{
// get device info from the devices listbox
WCHAR wdeviceinfo[100];
SendMessage(hwnddevices,
LB_GETTEXT,
static_cast<WPARAM>(SendMessage(hwnddevices,
LB_GETCURSEL, 0,0)),
reinterpret_cast<LPARAM>(wdeviceinfo));
wdeviceinfo[10]=0;
// convert acsii device ID to binary
WCHAR* stoppedhere;
DWORD wdeviceid=(DWORD)wcstol(wdeviceinfo+2,
&stoppedhere,16);
// fill out address structure with device id and service
_SOCKADDR_IRDA dest;
dest.irdaAddressFamily=AF_IRDA;
memcpy(dest.irdaDeviceID,&wdeviceid,sizeof(wdeviceid));
strcpy(dest.irdaServiceName,"basic_irda_server");
// attempt the connection
if (SOCKET_ERROR!=connect(sock,
reinterpret_cast<struct sockaddr *>(&dest),
sizeof(dest)))
{
•••
Figure 17 SOCKADR_IRDA Fragment
SOCKET sock=socket(irda_family_id,SOCK_STREAM,0);
if (sock!=SOCKET_ERROR)
{
// bind to irda, service name="basic_irda_server"
_SOCKADDR_IRDA sa;
memset(&sa,0,sizeof(sa));
sa.irdaAddressFamily=irda_family_id;
strcpy(sa.irdaServiceName,"basic_irda_server");
if (bind(sock,
reinterpret_cast<struct sockaddr *>(&sa),
sizeof(sa))!=SOCKET_ERROR)
{
// set async for connects
if (WSAAsyncSelect(sock,
hwnd,
WM_ASYNC_SOCKMSG,
FD_ACCEPT)!=SOCKET_ERROR)
{
// listen for connections
if (listen(sock,
min(SOMAXCONN,MAX_SUPPORTED_CONNECTIONS))
!=SOCKET_ERROR)
{
•••
Figure 18 build_device_list
void build_device_list(string &new_device_list)
{
// new device list string
new_device_list="";
if (irda_family_id!=-1)
{
// IrDA is running on this system
SOCKET sock=socket(irda_family_id,SOCK_STREAM,0);
if (sock!=SOCKET_ERROR)
{
// build device list structure - allow room for 50 devices
int dl_len=sizeof(DEVICELIST)*sizeof(IRDA_DEVICE_INFO)*49;
char *buf=new char[dl_len];
// query for the device list
int err=getsockopt(sock,
SOL_IRLMP,
IRLMP_ENUMDEVICES,
buf,
&dl_len);
if (err!=SOCKET_ERROR)
{
// got the device list
DEVICELIST *pdl=reinterpret_cast<DEVICELIST*>(buf);
if (pdl->numDevice)
{
// there are devices, iterate through them
for (int i=0;i<pdl->numDevice;i++)
{
// form a reference to the appropriate device
IRDA_DEVICE_INFO &di=pdl->Device[i];
// format the info into a string, and append to list
char buf[100];
sprintf(buf,"0x%08x; %04x %04x %04x; %s\n",
*reinterpret_cast<DWORD*>(&di.irdaDeviceID),
(WORD)di.irdaDeviceHints1,
(WORD)di.irdaDeviceHints2,
(WORD)di.irdaCharSet,
di.irdaDeviceName);
new_device_list+=buf;
}
}
}
delete [] buf; // delete the device buffer
closesocket(sock);
}
}
}
Figure 19 getsockopt and IAS_QUERY
SOCKET sock=socket(AF_IRDA,SOCK_STREAM,0);
if (SOCKET_ERROR!=sock) {
// get device info from the devices listbox
WCHAR wdeviceinfo[100];
SendMessage(hwnddevices,
LB_GETTEXT,
static_cast<WPARAM>(SendMessage(hwnddevices,LB_GETCURSEL,0,0)),
reinterpret_cast<LPARAM>(wdeviceinfo));
wdeviceinfo[10]=0;
// convert acsii device ID to binary
WCHAR* stoppedhere;
DWORD wdeviceid=(DWORD)wcstol(wdeviceinfo+2,&stoppedhere,16);
// the content of the edit box specifies the class to verify
WCHAR wclassname[200];
GetWindowText(hwnddata,wclassname,sizeof(wclassname));
// convert the class name to mbcs
char classname[200];
wcstombs(classname,wclassname,wcslen(wclassname)+1);
// initialize the query structure
_IAS_QUERY iasq;
memset(&iasq,0,sizeof(iasq));
int iasqlen=sizeof(iasq);
// copy in the device id, classname, and attribute
memcpy(iasq.irdaDeviceID,&wdeviceid,sizeof(wdeviceid));
strcpy(iasq.irdaClassName,classname);
// this means: return me the LSAP-SEL for the above class
strcpy(iasq.irdaAttribName,"IrDA:TinyTP:LsapSel");
// do the query
if (SOCKET_ERROR!=getsockopt(sock,
SOL_IRLMP,
IRLMP_IAS_QUERY,
reinterpret_cast<char*>(&iasq),
&iasqlen)==SOCKET_ERROR)
{
// the query worked
switch (iasq.irdaAttribType) {
case IAS_ATTRIB_NO_CLASS: {
// the class does not exist on the remote machine
MessageBox(hwnd,TEXT("Could not find class."),
TEXT("IAS Query Result:"),
MB_OK);
} break;
case IAS_ATTRIB_NO_ATTRIB: {
MessageBox(hwnd,TEXT("Could not find attribute."),
TEXT("IAS Query Result:"),
MB_OK);
} break;
default: {
// otherwise, that machine is running that service!
MessageBox(hwnd,TEXT("Class / Attribute found"),
TEXT("IAS Query Result:"),
MB_OK);
} break;
}
}
•••