static void OnData(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *value, void *info) { switch (type) { case kCFSocketDataCallBack: CFDataRef data(reinterpret_cast<CFDataRef>(value)); Client *client(reinterpret_cast<Client *>(info)); if (client->message_ == NULL) client->message_ = CFHTTPMessageCreateEmpty(kCFAllocatorDefault, TRUE); if (!CFHTTPMessageAppendBytes(client->message_, CFDataGetBytePtr(data), CFDataGetLength(data))) CFLog(kCFLogLevelError, CFSTR("CFHTTPMessageAppendBytes()")); else if (CFHTTPMessageIsHeaderComplete(client->message_)) { CFURLRef url(CFHTTPMessageCopyRequestURL(client->message_)); Boolean absolute; CFStringRef path(CFURLCopyStrictPath(url, &absolute)); CFRelease(client->message_); CFStringRef code(CFURLCreateStringByReplacingPercentEscapes(kCFAllocatorDefault, path, CFSTR(""))); CFRelease(path); JSStringRef script(JSStringCreateWithCFString(code)); CFRelease(code); JSValueRef result(JSEvaluateScript(CYGetJSContext(), script, NULL, NULL, 0, NULL)); JSStringRelease(script); CFHTTPMessageRef response(CFHTTPMessageCreateResponse(kCFAllocatorDefault, 200, NULL, kCFHTTPVersion1_1)); CFHTTPMessageSetHeaderFieldValue(response, CFSTR("Content-Type"), CFSTR("application/json; charset=utf-8")); CFStringRef json(CYCopyJSONString(CYGetJSContext(), result, NULL)); CFDataRef body(CFStringCreateExternalRepresentation(kCFAllocatorDefault, json, kCFStringEncodingUTF8, NULL)); CFRelease(json); CFStringRef length(CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%u"), CFDataGetLength(body))); CFHTTPMessageSetHeaderFieldValue(response, CFSTR("Content-Length"), length); CFRelease(length); CFHTTPMessageSetBody(response, body); CFRelease(body); CFDataRef serialized(CFHTTPMessageCopySerializedMessage(response)); CFRelease(response); CFSocketSendData(socket, NULL, serialized, 0); CFRelease(serialized); CFRelease(url); } break; } }
bool pSendSurrenderAccess( CFUUIDBytes pHostGuid, PNDAS_HIX_UNITDEVICE_ENTRY_DATA data, struct sockaddr_lpx *hostAddr ) { NDAS_HIX_SURRENDER_ACCESS_REQUEST request; CFDataRef cfdRequest = NULL; // Build Request. pBuildNHIXHeader( &request.Header, pHostGuid, 0, NHIX_TYPE_SURRENDER_ACCESS, sizeof(NDAS_HIX_SURRENDER_ACCESS_REQUEST) ); request.Data.EntryCount = 1; memcpy(&request.Data.Entry[0], data, sizeof(NDAS_HIX_UNITDEVICE_ENTRY_DATA)); cfdRequest = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (UInt8 *) &request, sizeof(NDAS_HIX_SURRENDER_ACCESS_REQUEST), kCFAllocatorNull); // Send Request. // Per Interface. CFSocketRef sockets[4]; int numInterfaces = 0; for(int i = 0; i < numberOfNics; i++) { CFDataRef address = 0; struct sockaddr_lpx addr = { 0 }; // Build Socket. sockets[numInterfaces] = CFSocketCreate ( kCFAllocatorDefault, PF_LPX, SOCK_DGRAM, 0, 0, 0, NULL ); if(sockets[numInterfaces] == NULL) { syslog(LOG_ERR, "pSendSurrenderAccess: Can't Create socket for surrender Access request."); return false; } // Bind Interface Address. addr.slpx_family = AF_LPX; addr.slpx_len = sizeof(struct sockaddr_lpx); addr.slpx_port = 0; memcpy(addr.slpx_node, ethernetData[i].macAddress, 6); address = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (UInt8 *) &addr, sizeof(struct sockaddr_lpx), kCFAllocatorNull); CFSocketError socketError = CFSocketSetAddress ( sockets[numInterfaces], address ); if(socketError != kCFSocketSuccess) { syslog(LOG_ERR, "pSendSurrenderAccess: Can't Bind."); continue; } if(address) CFRelease(address); address= NULL; // Bind Peer Host Address. address = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (UInt8 *) hostAddr, sizeof(struct sockaddr_lpx), kCFAllocatorNull); // Send Request. socketError = CFSocketSendData ( sockets[numInterfaces], address, cfdRequest, 0 ); if(socketError != kCFSocketSuccess) { syslog(LOG_ERR, "pSendSurrenderAccess: Error when send reply."); return false; } numInterfaces++; if(address) CFRelease(address); } if(cfdRequest) CFRelease(cfdRequest); // Receive Reply. int maxfdp1; socklen_t fromlen; fd_set rset; struct timeval timeout; bool bResult; struct sockaddr_lpx addr; int count; FD_ZERO(&rset); maxfdp1 = 0; for(count = 0; count < numInterfaces; count++) { FD_SET( CFSocketGetNative(sockets[count]), &rset); maxfdp1 = (maxfdp1 > CFSocketGetNative(sockets[count])) ? maxfdp1 : CFSocketGetNative(sockets[count]); } maxfdp1++; timeout.tv_sec = 20; // 20 sec. timeout.tv_usec = 0; int result = select(maxfdp1, &rset, NULL, NULL, &timeout); if(result > 0) { NDAS_HIX_SURRENDER_ACCESS_REPLY reply; for(count = 0; count < numInterfaces; count++) { if (FD_ISSET( CFSocketGetNative(sockets[count]), &rset)) { int len; len = recvfrom(CFSocketGetNative(sockets[count]), &reply, sizeof(NDAS_HIX_SURRENDER_ACCESS_REPLY), 0, (sockaddr *)&addr, &fromlen); if(reply.Data.Status == NHIX_SURRENDER_REPLY_STATUS_QUEUED) { bResult = true; } else { bResult = false; } } } } else { // Error or timeout. syslog(LOG_ERR, "pSendSurrenderAccess: select error or timeout %d\n", result); bResult = false; } //if(socketSurrender) CFRelease(socketSurrender); for(count = 0; count < numInterfaces; count++) { if(sockets[count]) CFRelease(sockets[count]); } return bResult; }
bool pSendUnitDeviceChangeNotification( CFUUIDBytes pHostGuid, PNDAS_HIX_UNITDEVICE_CHANGE_NOTIFY data ) { CFDataRef cfdRequest = NULL; // Build Request. pBuildNHIXHeader( &data->Header, pHostGuid, 0, NHIX_TYPE_UNITDEVICE_CHANGE, sizeof(NDAS_HIX_UNITDEVICE_CHANGE_NOTIFY) ); cfdRequest = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (UInt8 *) data, sizeof(NDAS_HIX_UNITDEVICE_CHANGE_NOTIFY), kCFAllocatorNull); // Send Request. // Per Interface. CFSocketRef sockets[16]; int numInterfaces = 0; for(int i = 0; i < numberOfNics; i++) { CFDataRef address = 0; struct sockaddr_lpx addr = { 0 }; // Build Socket. sockets[numInterfaces] = CFSocketCreate ( kCFAllocatorDefault, PF_LPX, SOCK_DGRAM, 0, 0, 0, NULL ); if(sockets[numInterfaces] == NULL) { syslog(LOG_ERR, "pSendSurrenderAccess: Can't Create socket for surrender Access request."); return false; } // Bind Interface Address. addr.slpx_family = AF_LPX; addr.slpx_len = sizeof(struct sockaddr_lpx); addr.slpx_port = 0; memcpy(addr.slpx_node, ethernetData[i].macAddress, 6); address = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (UInt8 *) &addr, sizeof(struct sockaddr_lpx), kCFAllocatorNull); CFSocketError socketError = CFSocketSetAddress ( sockets[numInterfaces], address ); if(socketError != kCFSocketSuccess) { syslog(LOG_ERR, "pSendSurrenderAccess: Can't Bind."); continue; } if(address) CFRelease(address); address= NULL; // Create Broadcast address. addr.slpx_family = AF_LPX; addr.slpx_len = sizeof(struct sockaddr_lpx); memset(addr.slpx_node, 0xff, 6); addr.slpx_port = htons(NDAS_HIX_LISTEN_PORT); address = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (UInt8 *) &addr, sizeof(struct sockaddr_lpx), kCFAllocatorNull); // Set Broadcast Flag. int on = 1; if(setsockopt(CFSocketGetNative(sockets[numInterfaces]), SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) != 0) { syslog(LOG_ERR, "pSendSurrenderAccess: Error when set option."); return false; } // Send Request. socketError = CFSocketSendData ( sockets[numInterfaces], address, cfdRequest, 0 ); if(socketError != kCFSocketSuccess) { syslog(LOG_ERR, "pSendSurrenderAccess: Error when send reply."); return false; } numInterfaces++; if(address) CFRelease(address); } if(cfdRequest) CFRelease(cfdRequest); return true; }
int pSendDiscover( CFUUIDBytes pHostGuid, PNDAS_HIX_UNITDEVICE_ENTRY_DATA data, struct sockaddr_lpx *host ) { NDAS_HIX_DISCOVER_REQUEST request; CFDataRef cfdRequest = NULL; // Build Request. pBuildNHIXHeader( &request.Header, pHostGuid, 0, NHIX_TYPE_DISCOVER, sizeof(NDAS_HIX_SURRENDER_ACCESS_REQUEST) ); request.Data.EntryCount = 1; memcpy(&request.Data.Entry[0], data, sizeof(NDAS_HIX_UNITDEVICE_ENTRY_DATA)); cfdRequest = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (UInt8 *) &request, sizeof(NDAS_HIX_SURRENDER_ACCESS_REQUEST), kCFAllocatorNull); // Send Request. // Per Interface. CFSocketRef sockets[4]; int numInterfaces = 0; for(int i = 0; i < numberOfNics; i++) { CFDataRef address = 0; struct sockaddr_lpx addr = { 0 }; // Build Socket. sockets[numInterfaces] = CFSocketCreate ( kCFAllocatorDefault, PF_LPX, SOCK_DGRAM, 0, 0, 0, NULL ); if(sockets[numInterfaces] == NULL) { syslog(LOG_ERR, "pSendSurrenderAccess: Can't Create socket for surrender Access request."); return -1; } // Bind Interface Address. addr.slpx_family = AF_LPX; addr.slpx_len = sizeof(struct sockaddr_lpx); addr.slpx_port = 0; memcpy(addr.slpx_node, ethernetData[i].macAddress, 6); address = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (UInt8 *) &addr, sizeof(struct sockaddr_lpx), kCFAllocatorNull); CFSocketError socketError = CFSocketSetAddress ( sockets[numInterfaces], address ); if(socketError != kCFSocketSuccess) { syslog(LOG_ERR, "pSendSurrenderAccess: Can't Bind."); continue; } if(address) CFRelease(address); address= NULL; // Create Broadcast address. addr.slpx_family = AF_LPX; addr.slpx_len = sizeof(struct sockaddr_lpx); memset(addr.slpx_node, 0xff, 6); addr.slpx_port = htons(NDAS_HIX_LISTEN_PORT); address = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (UInt8 *) &addr, sizeof(struct sockaddr_lpx), kCFAllocatorNull); // Set Broadcast Flag. int on = 1; if(setsockopt(CFSocketGetNative(sockets[numInterfaces]), SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) != 0) { syslog(LOG_ERR, "pSendSurrenderAccess: Error when set option."); return false; } // Send Request. socketError = CFSocketSendData ( sockets[numInterfaces], address, cfdRequest, 0 ); if(socketError != kCFSocketSuccess) { syslog(LOG_ERR, "pSendSurrenderAccess: Error when send reply."); return false; } numInterfaces++; if(address) CFRelease(address); } if(cfdRequest) CFRelease(cfdRequest); // Receive Reply. int maxfdp1; socklen_t fromlen; fd_set rset; struct timeval timeout; int bResult; struct sockaddr_lpx addr = { 0 }; int count; int numberOfHosts = 0; // HostID Dictionary. CFMutableDictionaryRef HostIDs = CFDictionaryCreateMutable ( kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks ); if (NULL == HostIDs) { return -1; } retry: FD_ZERO(&rset); maxfdp1 = 0; for(count = 0; count < numInterfaces; count++) { FD_SET( CFSocketGetNative(sockets[count]), &rset); maxfdp1 = (maxfdp1 > CFSocketGetNative(sockets[count])) ? maxfdp1 : CFSocketGetNative(sockets[count]); } maxfdp1++; timeout.tv_sec = 2; // 2 sec. timeout.tv_usec = 0; int result = select(maxfdp1, &rset, NULL, NULL, &timeout); if(result > 0) { NDAS_HIX_DISCOVER_REPLY reply; int len; fromlen = sizeof(struct sockaddr_lpx); // Find socket. for(count = 0; count < numInterfaces; count++) { if (FD_ISSET( CFSocketGetNative(sockets[count]), &rset)) { len = recvfrom(CFSocketGetNative(sockets[count]), &reply, sizeof(NDAS_HIX_DISCOVER_REPLY), 0, (sockaddr *)&addr, &fromlen); if ( len < sizeof(NDAS_HIX_DISCOVER_REPLY) ) { syslog(LOG_WARNING, "pSendDiscover: Too short HIX Discover reply len : %d\n", len); continue; } // syslog(LOG_ERR, "pSendDiscover: Host %2x:%2x:%2x:%2x:%2x:%2x %d\n", // addr.slpx_node[0], addr.slpx_node[1], addr.slpx_node[2], // addr.slpx_node[3], addr.slpx_node[4], addr.slpx_node[5], fromlen); // syslog(LOG_ERR, "pSendDiscover: Access : %x", reply.Data.Entry[0].AccessType); if ( len >= sizeof(NDAS_HIX_DISCOVER_REPLY) ) { if (reply.Data.EntryCount == 1 && memcmp(data->DeviceId, reply.Data.Entry[0].DeviceId, 6) == 0 && data->UnitNo == reply.Data.Entry[0].UnitNo) { // Check Duplecation. CFDataRef hostID = CFDataCreate( kCFAllocatorDefault, reply.Header.HostId, 16 ); if (NULL == hostID) { goto Out; } if (0 == CFDictionaryGetCountOfKey(HostIDs, hostID)) { // New Host. CFDictionarySetValue( HostIDs, hostID, hostID); syslog(LOG_DEBUG, "[%s] HIX Replay Type : %d\n", __FUNCTION__, reply.Data.Entry[0].AccessType); switch (reply.Data.Entry[0].AccessType) { case NHIX_UDA_WRITE_ACCESS: case NHIX_UDA_READ_WRITE_ACCESS: case NHIX_UDA_SHARED_READ_WRITE_SECONDARY_ACCESS: case NHIX_UDA_SHARED_READ_WRITE_PRIMARY_ACCESS: { numberOfHosts++; // Copy Address. if (host) { memcpy(host, &addr, sizeof(struct sockaddr_lpx)); } } break; default: break; } } else { syslog(LOG_INFO, "pSendDiscover: Duplicated replay."); } CFRelease(hostID); } } } } goto retry; } else { // Error or timeout. // syslog(LOG_ERR, "pSendDiscover: select error or timeout %d Hosts %d\n", result, numberOfHosts); bResult = numberOfHosts; } //if(socketSurrender) CFRelease(socketSurrender); Out: if (HostIDs) { CFDictionaryRemoveAllValues(HostIDs); CFRelease(HostIDs); } for(count = 0; count < numInterfaces; count++) { if(sockets[count]) CFRelease(sockets[count]); } return bResult; }