Net-Bluetooth
view release on metacpan or search on metacpan
str2uuid(service_buf, uuid);
}
else {
return(-1);
}
}
// 16 bit
else if(strlen(service) == 4) {
strcpy(service_buf, UUID_BASE_128);
service_buf[4] = service[0];
service_buf[5] = service[1];
service_buf[6] = service[2];
service_buf[7] = service[3];
str2uuid(service_buf, uuid);
}
else {
return(-1);
}
return(0);
}
MODULE = Net::Bluetooth PACKAGE = Net::Bluetooth
void
_init()
CODE:
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD(2, 0);
if(WSAStartup(wVersionRequested, &wsaData) != 0) {
croak("Could not init Winsock!");
}
void
_deinit()
CODE:
WSACleanup();
InOutStream
_perlfh(fd)
int fd
CODE:
InOutStream fh = PerlIO_fdopen(fd, "r+");
RETVAL = fh;
OUTPUT:
RETVAL
void
_close(sock)
int sock
PPCODE:
closesocket(sock);
unsigned int
_use_service_handle()
CODE:
// We dont use the service handle on Windows
RETVAL = 0;
OUTPUT:
RETVAL
void
get_remote_devices()
PPCODE:
int done = 0;
int iRet;
int error;
DWORD flags = 0;
DWORD qs_len;
HANDLE hLookup;
char addr_buf[64];
WSAQUERYSET *qs;
BTH_ADDR result;
HV *return_hash = NULL;
qs_len = sizeof(WSAQUERYSET);
qs = (WSAQUERYSET*) malloc(qs_len);
ZeroMemory(qs, sizeof(WSAQUERYSET));
qs->dwSize = sizeof(WSAQUERYSET);
qs->dwNameSpace = NS_BTH;
qs->lpcsaBuffer = NULL;
flags |= LUP_FLUSHCACHE | LUP_RETURN_NAME | LUP_RETURN_ADDR | LUP_CONTAINERS;
iRet = WSALookupServiceBegin(qs, flags, &hLookup);
// return undef if error and empty hash if no devices found?
if(iRet == SOCKET_ERROR) {
error = WSAGetLastError();
if(error == WSASERVICE_NOT_FOUND) {
// No device
WSALookupServiceEnd(hLookup);
free(qs);
}
else {
free(qs);
}
}
else {
EXTEND(sp, 1);
while(! done) {
if(WSALookupServiceNext(hLookup, flags, &qs_len, qs) == NO_ERROR) {
result = ((SOCKADDR_BTH*)qs->lpcsaBuffer->RemoteAddr.lpSockaddr)->btAddr;
ba2str(result, addr_buf);
if(return_hash == NULL)
return_hash = newHV();
if(qs->lpszServiceInstanceName == NULL || strlen(qs->lpszServiceInstanceName) == 0) {
hv_store(return_hash, addr_buf, strlen(addr_buf), newSVpv("[unknown]", 0), 0);
}
else {
hv_store(return_hash, addr_buf, strlen(addr_buf), newSVpv(qs->lpszServiceInstanceName, 0), 0);
}
}
else {
error = WSAGetLastError();
if(error == WSAEFAULT) {
free(qs);
qs = (WSAQUERYSET*) malloc(qs_len);
ZeroMemory(qs, qs_len);
}
else if(error == WSA_E_NO_MORE) {
done = 1;
}
else {
done = 1;
}
}
}
// only return if has values
if(return_hash != NULL)
PUSHs(sv_2mortal(newRV_inc((SV*) return_hash)));
WSALookupServiceEnd(hLookup);
}
void
sdp_search(addr, service, name)
char *addr
char *service
char *name
PPCODE:
char *addrstr = NULL;
char *uuidstr = "0";
char localAddressBuf[32];
DWORD qs_len;
WSAQUERYSET *qs;
DWORD flags;
HANDLE h;
GUID uuid;
SOCKADDR_BTH sa;
int sa_len = sizeof(sa);
int local_fd = 0;
int done = 0;
int proto;
int port;
int error;
HV *return_hash = NULL;
EXTEND(sp, 1);
// this prolly doesnt need to be malloced
// inquiry data structure
qs_len = sizeof(WSAQUERYSET);
qs = (WSAQUERYSET*) malloc(qs_len);
flags = LUP_FLUSHCACHE | LUP_RETURN_ALL;
ZeroMemory(qs, qs_len);
qs->dwSize = sizeof(WSAQUERYSET);
qs->dwNameSpace = NS_BTH;
// ignored for queries?
qs->dwNumberOfCsAddrs = 0;
if(_stricmp(addr, "localhost") == 0 || _stricmp(addr, "local") == 0 ) {
memset(&sa, 0, sizeof(sa));
local_fd = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
if(local_fd < 1) {
free(qs);
XSRETURN_UNDEF;
}
sa.addressFamily = AF_BTH;
sa.port = BT_PORT_ANY;
if(bind(local_fd,(LPSOCKADDR)&sa,sa_len) != NO_ERROR) {
free(qs);
close(local_fd);
XSRETURN_UNDEF;
}
if(getsockname(local_fd, (LPSOCKADDR)&sa, &sa_len) != NO_ERROR) {
free(qs);
close(local_fd);
XSRETURN_UNDEF;
}
ba2str(sa.btAddr, localAddressBuf);
qs->lpszContext = (LPSTR) localAddressBuf;
close(local_fd);
}
else {
qs->lpszContext = (LPSTR) addr;
// set protocol and port
proto = qs->lpcsaBuffer->iProtocol;
port = ((SOCKADDR_BTH*)qs->lpcsaBuffer->RemoteAddr.lpSockaddr)->port;
if(proto == BTHPROTO_RFCOMM) {
if(port) {
hv_store(return_hash, "RFCOMM", strlen("RFCOMM"), newSViv(port), 0);
}
}
else if(proto == BTHPROTO_L2CAP) {
if(port) {
hv_store(return_hash, "L2CAP", strlen("L2CAP"), newSViv(port), 0);
}
}
else {
if(port) {
hv_store(return_hash, "UNKNOWN", strlen("UNKNOWN"), newSViv(port), 0);
}
}
// qs->lpBlob->pBlobData and qs->lpBlob->cbSize give access to the raw service records
PUSHs(sv_2mortal(newRV_inc((SV*) return_hash)));
}
else {
error = WSAGetLastError();
if(error == WSAEFAULT) {;
free(qs);
qs = (WSAQUERYSET*) malloc(qs_len);
}
else if(error == WSA_E_NO_MORE) {
done = 1;
}
else {
done = 1;
}
}
}
}
WSALookupServiceEnd(h);
free(qs);
void
_register_service(serverfd, proto, port, service_id, name, desc, advertise)
int serverfd
char *proto
int port
char *service_id
char *name
char *desc
int advertise
PPCODE:
WSAQUERYSET qs;
WSAESETSERVICEOP op;
SOCKADDR_BTH sa;
int sa_len = sizeof(sa);
char *service_name = NULL;
char *service_desc = NULL;
char *service_class_id_str = NULL;
CSADDR_INFO sockInfo;
GUID uuid;
EXTEND(sp, 1);
memset(&qs, 0, sizeof(qs));
memset(&sa, 0, sizeof(sa));
memset(&sockInfo, 0, sizeof(sockInfo));
memset(&uuid, 0, sizeof(uuid));
op = advertise ? RNRSERVICE_REGISTER : RNRSERVICE_DELETE;
if(getsockname(serverfd, (SOCKADDR*) &sa, &sa_len) == SOCKET_ERROR) {
PUSHs(sv_2mortal(newSViv(1)));
XSRETURN_IV(0);
}
if(build_uuid(&uuid, service_id) != 0) {
XSRETURN_IV(0);
}
sockInfo.iProtocol = BTHPROTO_RFCOMM;
sockInfo.iSocketType = SOCK_STREAM;
sockInfo.LocalAddr.lpSockaddr = (LPSOCKADDR) &sa;
sockInfo.LocalAddr.iSockaddrLength = sizeof(sa);
sockInfo.RemoteAddr.lpSockaddr = (LPSOCKADDR) &sa;
sockInfo.RemoteAddr.iSockaddrLength = sizeof(sa);
qs.dwSize = sizeof(qs);
qs.dwNameSpace = NS_BTH;
qs.lpcsaBuffer = &sockInfo;
qs.lpszServiceInstanceName = name;
qs.lpszComment = name;
qs.lpServiceClassId = (LPGUID) &uuid;
qs.dwNumberOfCsAddrs = 1;
if(WSASetService(&qs, op, 0) == SOCKET_ERROR) {
PUSHs(sv_2mortal(newSViv(0)));
}
else {
PUSHs(sv_2mortal(newSViv(1)));
}
int
_stop_service(sdp_addr)
unsigned int sdp_addr
CODE:
// don't do anything here since we don't use handles
OUTPUT:
RETVAL
int
_bind(fd, port, proto)
int fd
int port
char *proto
CODE:
int status;
SOCKADDR_BTH sa;
int sa_len;
sa_len = sizeof(sa);
memset(&sa, 0, sa_len);
sa.btAddr = 0;
sa.addressFamily = AF_BTH;
sa.port = port;
status = bind(fd, (LPSOCKADDR)&sa, sa_len);
if(status == NO_ERROR) {
RETVAL = 0;
}
else {
RETVAL = -1;
}
OUTPUT:
RETVAL
int
_listen(fd, backlog)
int fd
int backlog
CODE:
int status;
status = listen(fd, backlog);
if(status == NO_ERROR) {
RETVAL = 0;
}
else {
RETVAL = -1;
}
OUTPUT:
RETVAL
void
_accept(fd, proto)
int fd
char *proto
PPCODE:
int addr_len;
int res;
char addr[19];
SOCKADDR_BTH rcaddr;
EXTEND(sp, 2);
addr_len = sizeof(rcaddr);
res = accept(fd, (LPSOCKADDR)&rcaddr, &addr_len);
if(res != INVALID_SOCKET) {
PUSHs(sv_2mortal(newSViv(res)));
ba2str(rcaddr.btAddr, addr);
PUSHs(sv_2mortal(newSVpv(addr, 0)));
}
else {
PUSHs(sv_2mortal(newSViv(-1)));
}
void
_getpeername(fd, proto)
int fd
char *proto
PPCODE:
EXTEND(sp, 2);
// not implemented for Windows yet
PUSHs(sv_2mortal(newSVuv(0)));
PUSHs(sv_2mortal(newSVuv(0)));
( run in 1.495 second using v1.01-cache-2.11-cpan-5511b514fd6 )