diff --git a/.gitignore b/.gitignore index 0def275..958706c 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ *.exe *.out *.app +*.sdf diff --git a/Chacha20/chacha20_simple.c b/Chacha20/chacha20_simple.c old mode 100644 new mode 100755 index dfe9471..c84569b --- a/Chacha20/chacha20_simple.c +++ b/Chacha20/chacha20_simple.c @@ -19,6 +19,12 @@ This implementation is intended to be simple, many optimizations can be performe #include #include "chacha20_simple.h" +#ifdef _WIN32 + #define INLINE +#else + #define INLINE inline +#endif + void chacha20_setup(chacha20_ctx *ctx, const uint8_t *key, size_t length, uint8_t nonce[8]) { const char *constants = (length == 32) ? "expand 32-byte k" : "expand 16-byte k"; @@ -123,7 +129,7 @@ void chacha20_encrypt(chacha20_ctx *ctx, const uint8_t *in, uint8_t *out, size_t } } -void chacha20_decrypt(chacha20_ctx *ctx, const uint8_t *in, uint8_t *out, size_t length) +void INLINE chacha20_decrypt(chacha20_ctx *ctx, const uint8_t *in, uint8_t *out, size_t length) { chacha20_encrypt(ctx, in, out, length); } diff --git a/Configuration.h b/Configuration.h old mode 100644 new mode 100755 index a59b45d..2bfe087 --- a/Configuration.h +++ b/Configuration.h @@ -17,7 +17,11 @@ #define _manufactuerName "ET Chan" //Manufactuer #define devicePassword "523-12-643" //Password #define deviceUUID "62F47751-8F26-46BF-9552-8F4238E67D60" //UUID, for pair verify +#ifdef _WIN32 +#define controllerRecordsAddress "PHK_controller" //Where to store the client keys +#else #define controllerRecordsAddress "/var/PHK_controller" //Where to store the client keys +#endif //Number of client /* @@ -38,6 +42,12 @@ #include #include + +#ifdef WIN32 +#include +#include +#else +#endif #include typedef SHA512_CTX SHACTX; diff --git a/PHKAccessory.cpp b/PHKAccessory.cpp index 2a510f5..1be2129 100755 --- a/PHKAccessory.cpp +++ b/PHKAccessory.cpp @@ -7,12 +7,15 @@ // #include "PHKAccessory.h" -#include "Configuration.h" const char hapJsonType[] = "application/hap+json"; const char pairingTlv8Type[] = "application/pairing+tlv8"; +//The default logger is printf +//Personal_homekit_set_logger_function can be changed. +PERSONAL_LOGGER_FUNCTION g_homekit_logger = printf; + //Wrap to JSON inline string wrap(const char *str) { return (string)"\""+str+"\""; } @@ -34,12 +37,12 @@ inline string attribute(unsigned short type, unsigned short acclaim, int p, bool result += "]"; result += ","; - char tempStr[4]; - snprintf(tempStr, 4, "%X", type); + char tempStr[9]; + snprintf(tempStr, 9, "%X", type); result += wrap("type")+":"+wrap(tempStr); result += ","; - snprintf(tempStr, 4, "%hd", acclaim); + snprintf(tempStr, 9, "%hd", acclaim); result += wrap("iid")+":"+tempStr; result += ","; @@ -47,26 +50,26 @@ inline string attribute(unsigned short type, unsigned short acclaim, int p, bool return "{"+result+"}"; } -inline string attribute(unsigned short type, unsigned short acclaim, int p, int value, int minVal, int maxVal, int step, unit valueUnit) { +inline string attribute(unsigned short type, unsigned short acclaim, int p, int value, int minVal, int maxVal, int step, unit valueUnit,const std::string& format ) { string result; - char tempStr[4]; + char tempStr[9]; - snprintf(tempStr, 4, "%d", value); + snprintf(tempStr, 9, "%d", value); if (p & premission_read) { result += wrap("value")+":"+tempStr; result += ","; } - snprintf(tempStr, 4, "%d", minVal); + snprintf(tempStr, 9, "%d", minVal); if (minVal != INT32_MIN) result += wrap("minValue")+":"+tempStr+","; - snprintf(tempStr, 4, "%d", maxVal); + snprintf(tempStr, 9, "%d", maxVal); if (maxVal != INT32_MAX) result += wrap("maxValue")+":"+tempStr+","; - snprintf(tempStr, 4, "%d", step); + snprintf(tempStr, 9, "%d", step); if (step > 0) result += wrap("minStep")+":"+tempStr+","; @@ -79,11 +82,11 @@ inline string attribute(unsigned short type, unsigned short acclaim, int p, int result += "]"; result += ","; - snprintf(tempStr, 4, "%X", type); + snprintf(tempStr, 9, "%X", type); result += wrap("type")+":"+wrap(tempStr); result += ","; - snprintf(tempStr, 4, "%hd", acclaim); + snprintf(tempStr, 9, "%hd", acclaim); result += wrap("iid")+":"+tempStr; result += ","; @@ -99,30 +102,30 @@ inline string attribute(unsigned short type, unsigned short acclaim, int p, int break; } - result += "\"format\":\"int\""; + result += "\"format\":\"" + format + "\""; return "{"+result+"}"; } inline string attribute(unsigned short type, unsigned short acclaim, int p, float value, float minVal, float maxVal, float step, unit valueUnit) { string result; - char tempStr[4]; + char tempStr[9]; - snprintf(tempStr, 4, "%f", value); + snprintf(tempStr, 9, "%f", value); if (p & premission_read) { result += wrap("value")+":"+tempStr; result += ","; } - snprintf(tempStr, 4, "%f", minVal); + snprintf(tempStr, 9, "%f", minVal); if (minVal != INT32_MIN) result += wrap("minValue")+":"+tempStr+","; - snprintf(tempStr, 4, "%f", maxVal); + snprintf(tempStr, 9, "%f", maxVal); if (maxVal != INT32_MAX) result += wrap("maxValue")+":"+tempStr+","; - snprintf(tempStr, 4, "%f", step); + snprintf(tempStr, 9, "%f", step); if (step > 0) result += wrap("minStep")+":"+tempStr+","; @@ -135,11 +138,11 @@ inline string attribute(unsigned short type, unsigned short acclaim, int p, floa result += "]"; result += ","; - snprintf(tempStr, 4, "%X", type); + snprintf(tempStr, 9, "%X", type); result += wrap("type")+":"+wrap(tempStr); result += ","; - snprintf(tempStr, 4, "%hd", acclaim); + snprintf(tempStr, 9, "%hd", acclaim); result += wrap("iid")+":"+tempStr; result += ","; @@ -161,7 +164,7 @@ inline string attribute(unsigned short type, unsigned short acclaim, int p, floa } inline string attribute(unsigned short type, unsigned short acclaim, int p, string value, unsigned short len) { string result; - char tempStr[4]; + char tempStr[9]; if (p & premission_read) { result += wrap("value")+":"+wrap(value.c_str()); @@ -177,16 +180,16 @@ inline string attribute(unsigned short type, unsigned short acclaim, int p, stri result += "]"; result += ","; - snprintf(tempStr, 4, "%X", type); + snprintf(tempStr, 9, "%X", type); result += wrap("type")+":"+wrap(tempStr); result += ","; - snprintf(tempStr, 4, "%hd", acclaim); + snprintf(tempStr, 9, "%hd", acclaim); result += wrap("iid")+":"+tempStr; result += ","; if (len > 0) { - snprintf(tempStr, 4, "%hd", len); + snprintf(tempStr, 9, "%hd", len); result += wrap("maxLen")+":"+tempStr; result += ","; } @@ -234,7 +237,11 @@ string floatCharacteristics::describe() { } string intCharacteristics::describe() { - return attribute(type, iid, premission, _value, _minVal, _maxVal, _step, _unit); + return attribute(type, iid, premission, _value, _minVal, _maxVal, _step, _unit, "int"); +} + +string uint8Characteristics::describe() { + return attribute(type, iid, premission, _value, _minVal, _maxVal, _step, _unit, "uint8"); } string stringCharacteristics::describe() { @@ -245,13 +252,13 @@ string Service::describe() { string keys[3] = {"iid", "type", "characteristics"}; string values[3]; { - char temp[8]; - snprintf(temp, 8, "%d", serviceID); + char temp[9]; + snprintf(temp, 9, "%d", serviceID); values[0] = temp; } { - char temp[8]; - snprintf(temp, 8, "\"%X\"", uuid); + char temp[9]; + snprintf(temp, 9, "\"%X\"", uuid); values[1] = temp; } { @@ -272,8 +279,8 @@ string Accessory::describe() { { keys[0] = "aid"; - char temp[8]; - sprintf(temp, "%d", aid); + char temp[9]; + snprintf(temp,9, "%d", aid); values[0] = temp; } @@ -293,20 +300,36 @@ string Accessory::describe() { return result; } + + +void AccessorySet::lock() +{ + pthread_mutex_lock(&this->accessoryMutex); +} + +void AccessorySet::unlock() +{ + pthread_mutex_unlock(&this->accessoryMutex); +} + + string AccessorySet::describe() { int numberOfAcc = numberOfAccessory(); - string *desc = new string[numberOfAcc]; + vector desc_vec(numberOfAcc); + string *desc = &desc_vec[0]; for (int i = 0; i < numberOfAcc; i++) { desc[i] = _accessories[i]->describe(); } string result = arrayWrap(desc, numberOfAcc); - delete [] desc; string key = "accessories"; result = dictionaryWrap(&key, &result, 1); return result; } + + struct broadcastInfo { + pthread_t thread; void *sender; char *desc; }; @@ -320,14 +343,18 @@ void *announce(void *info) { int len = snprintf(reply, 1024, "EVENT/1.0 200 OK\r\nContent-Type: application/hap+json\r\nContent-Length: %lu\r\n\r\n%s", strlen(desc), desc); #if HomeKitLog == 1 && HomeKitReplyHeaderLog==1 - printf("%s\n", reply); + g_homekit_logger("%s\n", reply); #endif + pthread_t currentthread = _info->thread; broadcastMessage(sender, reply, len); delete [] reply; delete [] desc; delete [] info; + + pthread_detach(currentthread); + return NULL; } void updateValueFromDeviceEnd(characteristics *c, int aid, int iid, string value) { @@ -337,14 +364,13 @@ void updateValueFromDeviceEnd(characteristics *c, int aid, int iid, string value broadcastInfo * info = new broadcastInfo; info->sender = c; info->desc = broadcastTemp; - pthread_t thread; - pthread_create(&thread, NULL, announce, info); + pthread_create(&info->thread, NULL, announce, info); } void handleAccessory(const char *request, unsigned int requestLen, char **reply, unsigned int *replyLen, connectionInfo *sender) { #if HomeKitLog == 1 - printf("Receive request: %s\n", request); + g_homekit_logger("Receive request: %s\n", request); #endif int index = 5; char method[5]; @@ -365,7 +391,7 @@ void handleAccessory(const char *request, unsigned int requestLen, char **reply, } path[i] = 0; #if HomeKitLog == 1 - printf("Path: %s\n", path); + g_homekit_logger("Path: %s\n", path); #endif const char *dataPtr = request; @@ -378,7 +404,7 @@ void handleAccessory(const char *request, unsigned int requestLen, char **reply, char *replyData = NULL; unsigned short replyDataLen = 0; - int statusCode; + int statusCode = 0; const char *protocol = "HTTP/1.1"; const char *returnType = hapJsonType; @@ -386,7 +412,7 @@ void handleAccessory(const char *request, unsigned int requestLen, char **reply, if (strcmp(path, "/accessories") == 0) { //Publish the characterists of the accessories #if HomeKitLog == 1 - printf("Ask for accessories info\n"); + g_homekit_logger("Ask for accessories info\n"); #endif statusCode = 200; string desc = AccessorySet::getInstance().describe(); @@ -397,16 +423,18 @@ void handleAccessory(const char *request, unsigned int requestLen, char **reply, } else if (strcmp(path, "/pairings") == 0) { PHKNetworkMessage msg(request); statusCode = 200; - printf("%d\n", *msg.data.dataPtrForIndex(0)); - if (*msg.data.dataPtrForIndex(0) == 3) { +#if HomeKitLog == 1 + g_homekit_logger("%d\n", *msg.data.dataPtrForIndex(0)); +#endif + if (*msg.data.dataPtrForIndex(0) == 3) { //Pairing with new user #if HomeKitLog == 1 - printf("Add new user\n"); + g_homekit_logger("Add new user\n"); #endif PHKKeyRecord controllerRec; bcopy(msg.data.dataPtrForIndex(3), controllerRec.publicKey, 32); bcopy(msg.data.dataPtrForIndex(1), controllerRec.controllerID, 36); - addControllerKey(controllerRec); + AccessorySet::getInstance().Controllers.addControllerKey(controllerRec); PHKNetworkMessageDataRecord drec; drec.activate = true; drec.data = new char[1]; *drec.data = 2; drec.index = 6; drec.length = 1; @@ -417,11 +445,11 @@ void handleAccessory(const char *request, unsigned int requestLen, char **reply, statusCode = 200; } else { #if HomeKitLog == 1 - printf("Delete user"); + g_homekit_logger("Delete user"); #endif PHKKeyRecord controllerRec; bcopy(msg.data.dataPtrForIndex(1), controllerRec.controllerID, 36); - removeControllerKey(controllerRec); + AccessorySet::getInstance().Controllers.removeControllerKey(controllerRec); PHKNetworkMessageDataRecord drec; drec.activate = true; drec.data = new char[1]; *drec.data = 2; drec.index = 6; drec.length = 1; @@ -432,32 +460,39 @@ void handleAccessory(const char *request, unsigned int requestLen, char **reply, statusCode = 200; } } else if (strncmp(path, "/characteristics", 16) == 0){ - pthread_mutex_lock(&AccessorySet::getInstance().accessoryMutex); - printf("Characteristics\n"); - if (strncmp(method, "GET", 3) == 0) { + AccessorySetAutoLock autolock; +#if HomeKitLog == 1 + g_homekit_logger("Characteristics\n"); +#endif + if (strncmp(method, "GET", 3) == 0) { //Read characteristics int aid = 0; int iid = 0; - char indexBuffer[1000]; - sscanf(path, "/characteristics?id=%[^\n]", indexBuffer); - printf("Get characteristics %s with len %d\n", indexBuffer, strlen(indexBuffer)); - + char indexBuffer[1000+1]={0}; + sscanf(path, "/characteristics?id=%1000[^\n]", indexBuffer); +#if HomeKitLog == 1 + g_homekit_logger("Get characteristics %s with len %d\n", indexBuffer, strlen(indexBuffer)); +#endif statusCode = 404; string result = "["; while (strlen(indexBuffer) > 0) { - printf("Get characteristics %s with len %d\n", indexBuffer, strlen(indexBuffer)); - - char temp[1000]; +#if HomeKitLog == 1 + g_homekit_logger("Get characteristics %s with len %d\n", indexBuffer, strlen(indexBuffer)); +#endif + char temp[1000+1]={0}; //Initial the temp - temp[0] = 0; - sscanf(indexBuffer, "%d.%d%[^\n]", &aid, &iid, temp); - printf("Get temp %s with len %d\n", temp, strlen(temp)); - strncpy(indexBuffer, temp, 1000); - printf("Get characteristics %s with len %d\n", indexBuffer, strlen(indexBuffer)); - //Trim comma + sscanf(indexBuffer, "%d.%d%1000[^\n]", &aid, &iid, temp); +#if HomeKitLog == 1 + g_homekit_logger("Get temp %s with len %d\n", temp, strlen(temp)); +#endif + strncpy(indexBuffer, temp, 1000); +#if HomeKitLog == 1 + g_homekit_logger("Get characteristics %s with len %d\n", indexBuffer, strlen(indexBuffer)); +#endif + //Trim comma if (indexBuffer[0] == ',') { indexBuffer[0] = '0'; } @@ -467,11 +502,11 @@ void handleAccessory(const char *request, unsigned int requestLen, char **reply, characteristics *c = a->characteristicsAtIndex(iid); if (c != NULL) { #if HomeKitLog == 1 - printf("Ask for one characteristics: %d . %d\n", aid, iid); + g_homekit_logger("Ask for one characteristics: %d . %d\n", aid, iid); #endif - char c1[3], c2[3]; - sprintf(c1, "%d", aid); - sprintf(c2, "%d", iid); + char c1[9], c2[9]; + snprintf(c1,9, "%d", aid); + snprintf(c2,9, "%d", iid); string s[3] = {string(c1), string(c2), c->value()}; string k[3] = {"aid", "iid", "value"}; if (result.length() != 1) { @@ -500,8 +535,8 @@ void handleAccessory(const char *request, unsigned int requestLen, char **reply, } else if (strncmp(method, "PUT", 3) == 0) { //Change characteristics - char characteristicsBuffer[1000]; - sscanf(dataPtr, "{\"characteristics\":[{%[^]]s}", characteristicsBuffer); + char characteristicsBuffer[1000+1]={0}; + sscanf(dataPtr, "{\"characteristics\":[{%1000[^]]}", characteristicsBuffer); char *buffer2 = characteristicsBuffer; while (strlen(buffer2) && statusCode != 400) { @@ -510,15 +545,15 @@ void handleAccessory(const char *request, unsigned int requestLen, char **reply, buffer1 = strtok_r(buffer2, "}", &buffer2); if (*buffer2 != 0) buffer2+=2; - int aid = 0; int iid = 0; char value[16]; - int result = sscanf(buffer1, "\"aid\":%d,\"iid\":%d,\"value\":%s", &aid, &iid, value); + int aid = 0; int iid = 0; char value[16+1]={0}; + int result = sscanf(buffer1, "\"aid\":%d,\"iid\":%d,\"value\":%16s", &aid, &iid, value); if (result == 2) { - sscanf(buffer1, "\"aid\":%d,\"iid\":%d,\"ev\":%s", &aid, &iid, value); + sscanf(buffer1, "\"aid\":%d,\"iid\":%d,\"ev\":%16s", &aid, &iid, value); updateNotify = true; } else if (result == 0) { - sscanf(buffer1, "\"remote\":true,\"value\":%[^,],\"aid\":%d,\"iid\":%d", value, &aid, &iid); + sscanf(buffer1, "\"remote\":true,\"value\":%16[^,],\"aid\":%d,\"iid\":%d", value, &aid, &iid); if (result == 2) { - sscanf(buffer1, "\"remote\":true,\"aid\":%d,\"iid\":%d,\"ev\":%s", &aid, &iid, value); + sscanf(buffer1, "\"remote\":true,\"aid\":%d,\"iid\":%d,\"ev\":%16s", &aid, &iid, value); updateNotify = true; } } @@ -531,7 +566,7 @@ void handleAccessory(const char *request, unsigned int requestLen, char **reply, if (updateNotify) { #if HomeKitLog == 1 - printf("Ask to notify one characteristics: %d . %d -> %s\n", aid, iid, value); + g_homekit_logger("Ask to notify one characteristics: %d . %d -> %s\n", aid, iid, value); #endif if (c==NULL) { statusCode = 400; @@ -546,7 +581,7 @@ void handleAccessory(const char *request, unsigned int requestLen, char **reply, } } else { #if HomeKitLog == 1 - printf("Ask to change one characteristics: %d . %d -> %s\n", aid, iid, value); + g_homekit_logger("Ask to change one characteristics: %d . %d -> %s\n", aid, iid, value); #endif if (c==NULL) { statusCode = 400; @@ -559,8 +594,7 @@ void handleAccessory(const char *request, unsigned int requestLen, char **reply, broadcastInfo * info = new broadcastInfo; info->sender = c; info->desc = broadcastTemp; - pthread_t thread; - pthread_create(&thread, NULL, announce, info); + pthread_create(&info->thread, NULL, announce, info); statusCode = 204; @@ -577,23 +611,23 @@ void handleAccessory(const char *request, unsigned int requestLen, char **reply, } else { return; } - pthread_mutex_unlock(&AccessorySet::getInstance().accessoryMutex); } else { //Error #if HomeKitLog == 1 - printf("Ask for something I don't know\n"); + g_homekit_logger("Ask for something I don't know\n"); + g_homekit_logger("%s\n", request); + g_homekit_logger("%s", path); #endif - printf("%s\n", request); - printf("%s", path); statusCode = 404; } //Calculate the length of header - char * tmp = new char[256]; - bzero(tmp, 256); - int len = snprintf(tmp, 256, "%s %d OK\r\nContent-Type: %s\r\nContent-Length: %u\r\n\r\n", protocol, statusCode, returnType, replyDataLen); - delete [] tmp; - + int len = 0; + { + char tmp[256]; + len = snprintf(tmp, 256, "%s %d OK\r\nContent-Type: %s\r\nContent-Length: %u\r\n\r\n", protocol, statusCode, returnType, replyDataLen); + } + //replyLen should omit the '\0'. (*replyLen) = len+replyDataLen; //reply should add '\0', or the printf is incorrect @@ -607,7 +641,7 @@ void handleAccessory(const char *request, unsigned int requestLen, char **reply, } #if HomeKitLog == 1 && HomeKitReplyHeaderLog==1 - printf("Reply: %s\n", *reply); + g_homekit_logger("Reply: %s\n", *reply); #endif } @@ -637,3 +671,8 @@ void addInfoServiceToAccessory(Accessory *acc, string accName, string manufactue identify->valueChangeFunctionCall = identifyCallback; acc->addCharacteristics(infoService, identify); } + +void Personal_homekit_set_logger_function(PERSONAL_LOGGER_FUNCTION func) +{ + g_homekit_logger = func; +} diff --git a/PHKAccessory.h b/PHKAccessory.h index 6ef068c..9c18a55 100755 --- a/PHKAccessory.h +++ b/PHKAccessory.h @@ -1,437 +1,547 @@ -#pragma once -// -// PHKAccessory.h -// Workbench -// -// Created by Wai Man Chan on 9/27/14. -// -// - -#include -#include -#define __STDC_LIMIT_MACROS -#include -extern "C" { -#include -} - -#include "PHKNetworkIP.h" - -#include "PHKControllerRecord.h" - -extern "C" { -#include "PHKArduinoLightInterface.h" -} - -#include - -#if MCU -#else -#include -#endif - -using namespace std; - -typedef enum { - charType_adminOnlyAccess = 0x1, - charType_audioChannels = 0x2, - charType_audioCodexName = 0x3, - charType_audioCodexParameter= 0x4, - charType_audioFeedback = 0x5, - charType_audioPropAttr = 0x6, - charType_audioValAttr = 0x7, - charType_brightness = 0x8, - charType_cameraNightVision = 0x9, - charType_cameraPan = 0xA, - charType_cameraTilt = 0xB, - charType_cameraZoom = 0xC, - charType_coolingThreshold = 0xD, - charType_currentDoorState = 0xE, - charType_currentHeatCoolMode= 0xF, - charType_currentHumidity = 0x10, - charType_currentTemperature = 0x11, - charType_heatingThreshold = 0x12, - charType_hue = 0x13, - charType_identify = 0x14, - charType_inputVolume = 0x15, - charType_ipCameraStart = 0x16, - charType_ipCameraStop = 0x17, - charType_lockControlPoint = 0x19, - charType_lockAutoTimeout = 0x1A, - charType_lockLastAction = 0x1C, - charType_lockCurrentState = 0x1D, - charType_lockTargetState = 0x1E, - charType_logs = 0x1F, - charType_manufactuer = 0x20, - charType_modelName = 0x21, - charType_motionDetect = 0x22, - charType_serviceName = 0x23, - charType_obstruction = 0x24, - charType_on = 0x25, - charType_outletInUse = 0x26, - charType_outputVolume = 0x27, - charType_rotationDirection = 0x28, - charType_rotationSpeed = 0x29, - charType_rtcpExtProp = 0x2A, - charType_rtcpVideoPayload = 0x2B, - charType_rtcpAudioPayload = 0x2C, - charType_rtcpAudioClock = 0x2D, - charType_rtcpProtocol = 0x2E, - charType_saturation = 0x2F, - charType_serialNumber = 0x30, - charType_srtpCyptoSuite = 0x31, - charType_targetDoorState = 0x32, - charType_targetHeatCoolMode = 0x33, - charType_targetHumidity = 0x34, - charType_targetTemperature = 0x35, - charType_temperatureUnit = 0x36, - charType_version = 0x37, - charType_videoCodexName = 0x38, - charType_videoCodexPara = 0x39, - charType_videoMirror = 0x3A, - charType_videoPropAttr = 0x3B, - charType_videoRotation = 0x3C, - charType_videoValAttr = 0x3D, - -#pragma - The following is only default by the device after iOS 9 - - charType_firmwareRevision = 0x52, - charType_hardwareRevision = 0x53, - charType_softwareRevision = 0x54, - - charType_reachable = 0x63, - - charType_airParticulateDensity = 0x64, - charType_airParticulateSize = 0x65, - charType_airQuality = 0x95, - charType_carbonDioxideDetected = 0x92, - charType_carbonMonoxideDetected = 0x69, - charType_carbonDioxideLevel = 0x93, - charType_carbonMonoxideLevel = 0x90, - charType_carbonDioxidePeakLevel = 0x94, - charType_carbonMonoxidePeakLevel = 0x91, - charType_smokeDetected = 0x76, - - charType_alarmCurrentState = 0x66, - charType_alarmTargetState = 0x67, - charType_batteryLevel = 0x68, - charType_contactSensorState = 0x6A, - charType_holdPosition = 0x6F, - charType_leakDetected = 0x70, - charType_occupancyDetected = 0x71, - - charType_currentAmbientLightLevel = 0x6B, - charType_currentHorizontalTiltAngle = 0x6C, - charType_targetHorizontalTiltAngle = 0x7B, - charType_currentPosition = 0x6D, - charType_targetPosition = 0x7C, - charType_currentVerticalTiltAngle = 0x6E, - charType_targetVerticalTiltAngle = 0x7D, - - charType_positionState = 0x72, - charType_programmableSwitchEvent = 0x73, - charType_programmableSwitchOutputState = 0x74, - - charType_sensorActive = 0x75, - charType_sensorFault = 0x77, - charType_sensorJammed = 0x78, - charType_sensorLowBattery = 0x79, - charType_sensorTampered = 0x7A, - charType_sensorChargingState= 0x8F, - - -#pragma - The following is service provide - serviceType_accessoryInfo = 0x3E, - serviceType_camera = 0x3F, - serviceType_fan = 0x40, - serviceType_garageDoorOpener = 0x41, - serviceType_lightBulb = 0x43, - serviceType_lockManagement = 0x44, - serviceType_lockMechanism = 0x45, - serviceType_microphone = 0x46, - serviceType_outlet = 0x47, - serviceType_speaker = 0x48, - serviceType_switch = 0x49, - serviceType_thermostat = 0x4A, - - serviceType_alarmSystem = 0x7E, - serviceType_bridgingState = 0x62, - serviceType_carbonMonoxideSensor = 0x7F, - serviceType_contactSensor = 0x80, - serviceType_door = 0x81, - serviceType_humiditySensor = 0x82, - serviceType_leakSensor = 0x83, - serviceType_lightSensor = 0x84, - serviceType_motionSensor = 0x85, - serviceType_occupancySensor = 0x86, - serviceType_smokeSensor = 0x87, - serviceType_programmableSwitch_stateful = 0x88, - serviceType_programmableSwitch_stateless = 0x89, - serviceType_temperatureSensor = 0x8A, - serviceType_window = 0x8B, - serviceType_windowCover = 0x8C, - serviceType_airQualitySensor = 0x8C, - serviceType_securityAlarm = 0x8E, - serviceType_charging = 0x8F, - - serviceType_battery = 0x96, - serviceType_carbonDioxideSensor= 0x97, - -#pragma - The following is for bluetooth characteristic - btCharType_pairSetup = 0x4C, - btCharType_pairVerify = 0x4E, - btCharType_pairingFeature = 0x4F, - btCharType_pairings = 0x50, - btCharType_serviceInstanceID = 0x51, -#pragma - The following is for bluetooth service - btServiceType_accessoryInformation = 0xFED3, - btServiceType_camera = 0xFEC9, - btServiceType_fan = 0xFECB, - btServiceType_garageDoorOpener = 0xFECE, - btServiceType_lightBulb = 0xFED2, - btServiceType_lockManagement = 0xFECF, - btServiceType_lockMechanism = 0xFED0, - btServiceType_microphone = 0xFEC8, - btServiceType_outlet = 0xFECC, - btServiceType_speaker = 0xFEC7, - btServiceType_switch = 0xFECD, - -} charType; - -enum { - premission_read = 1, - premission_write = 1 << 1, - premission_notify = 1 << 2 //Notify = Accessory will notice the controller -}; - -typedef enum { - unit_none = 0, - unit_celsius, - unit_percentage, - unit_arcDegree -} unit; - - -class characteristics { -public: - - const unsigned short type; - const int premission; - int iid; - characteristics(unsigned short _type, int _premission): type(_type), premission(_premission) {} - virtual string value() = 0; - virtual void setValue(string str) = 0; - virtual string describe() = 0; - bool writable() { return premission&premission_write; } - bool notifiable() { return premission&premission_notify; } -}; - -//To store value of device state, subclass the following type -class boolCharacteristics: public characteristics { -public: - bool _value; - void (*valueChangeFunctionCall)(bool oldValue, bool newValue) = NULL; - boolCharacteristics(unsigned short _type, int _premission): characteristics(_type, _premission) {} - virtual string value() { - if (_value) - return "1"; - return "0"; - } - virtual void setValue(string str) { - bool newValue = (strncmp("true", str.c_str(), 4)==0); - if (valueChangeFunctionCall) - valueChangeFunctionCall(_value, newValue); - _value = newValue; - } - virtual string describe(); -}; - -class floatCharacteristics: public characteristics { -public: - float _value; - const float _minVal, _maxVal, _step; - const unit _unit; - void (*valueChangeFunctionCall)(float oldValue, float newValue) = NULL; - floatCharacteristics(unsigned short _type, int _premission, float minVal, float maxVal, float step, unit charUnit): characteristics(_type, _premission), _minVal(minVal), _maxVal(maxVal), _step(step), _unit(charUnit) {} - virtual string value() { - char temp[16]; - snprintf(temp, 16, "%f", _value); - return temp; - } - virtual void setValue(string str) { - float temp = atof(str.c_str()); - if (temp == temp) { - if (valueChangeFunctionCall) - valueChangeFunctionCall(_value, temp); - _value = temp; - } - } - virtual string describe(); -}; - -class intCharacteristics: public characteristics { -public: - int _value; - const int _minVal, _maxVal, _step; - const unit _unit; - void (*valueChangeFunctionCall)(int oldValue, int newValue) = NULL; - intCharacteristics(unsigned short _type, int _premission, int minVal, int maxVal, int step, unit charUnit): characteristics(_type, _premission), _minVal(minVal), _maxVal(maxVal), _step(step), _unit(charUnit) { - _value = minVal; - } - virtual string value() { - char temp[16]; - snprintf(temp, 16, "%d", _value); - return temp; - } - virtual void setValue(string str) { - float temp = atoi(str.c_str()); - if (temp == temp) { - if (valueChangeFunctionCall) - valueChangeFunctionCall(_value, temp); - _value = temp; - } - } - virtual string describe(); -}; - -class stringCharacteristics: public characteristics { -public: - string _value; - const unsigned short maxLen; - void (*valueChangeFunctionCall)(string oldValue, string newValue) = NULL; - stringCharacteristics(unsigned short _type, int _premission, unsigned short _maxLen): characteristics(_type, _premission), maxLen(_maxLen) {} - virtual string value() { - return "\""+_value+"\""; - } - virtual void setValue(string str) { - if (valueChangeFunctionCall) - valueChangeFunctionCall(_value, str); - _value = str; - } - virtual string describe(); -}; - -//Abstract Layer of object -class Service { -public: - int serviceID, uuid; - vector _characteristics; - Service(int _uuid): uuid(_uuid) {} - virtual short numberOfCharacteristics() { return _characteristics.size(); } - virtual characteristics *characteristicsAtIndex(int index) { return _characteristics[index]; } - string describe(); -}; - -class Accessory { -public: - int numberOfInstance = 0; - int aid; - vector_services; - void addService(Service *ser) { - ser->serviceID = ++numberOfInstance; - _services.push_back(ser); - } - void addCharacteristics(Service *ser, characteristics *cha) { - cha->iid = ++numberOfInstance; - ser->_characteristics.push_back(cha); - } - bool removeService(Service *ser) { - bool exist = false; - for (vector::iterator it = _services.begin(); it != _services.end(); it++) { - if (*it == ser) { - _services.erase(it); - exist = true; - } - } - return exist; - } - bool removeCharacteristics(characteristics *cha) { - bool exist = false; - for (vector::iterator it = _services.begin(); it != _services.end(); it++) { - for (vector::iterator jt = (*it)->_characteristics.begin(); jt != (*it)->_characteristics.end(); jt++) { - if (*jt == cha) { - (*it)->_characteristics.erase(jt); - exist = true; - } - } - } - return exist; - } - Accessory() {} - short numberOfService() { return _services.size(); } - Service *serviceAtIndex(int index) { - for (vector::iterator it = _services.begin(); it != _services.end(); it++) { - if ((*it)->serviceID == index) { - return *it; - } - } - return NULL; - } - characteristics *characteristicsAtIndex(int index) { - for (vector::iterator it = _services.begin(); it != _services.end(); it++) { - for (vector::iterator jt = (*it)->_characteristics.begin(); jt != (*it)->_characteristics.end(); jt++) { - if ((*jt)->iid == index) { - return *jt; - } - } - } - return NULL; - } - string describe(); -}; - -class AccessorySet { -private: - vector _accessories; - int _aid = 0; - AccessorySet() { - pthread_mutex_init(&accessoryMutex, NULL); - } - AccessorySet(AccessorySet const&); - void operator=(AccessorySet const&); -public: - static AccessorySet& getInstance() { - static AccessorySet instance; - - return instance; - } - pthread_mutex_t accessoryMutex; - short numberOfAccessory() { - return _accessories.size(); - } - Accessory *accessoryAtIndex(int index) { - for (vector::iterator it = _accessories.begin(); it != _accessories.end(); it++) { - if ((*it)->aid == index) { - return *it; - } - } - return NULL; - } - void addAccessory(Accessory *acc) { - acc->aid = ++_aid; - _accessories.push_back(acc); - } - bool removeAccessory(Accessory *acc) { - bool exist = false; - for (vector::iterator it = _accessories.begin(); it != _accessories.end(); it++) { - if (*it == acc) { - _accessories.erase(it); - exist = true; - } - } - return exist; - } - ~AccessorySet() { - pthread_mutex_destroy(&accessoryMutex); - } - string describe(); -}; - -typedef void (*identifyFunction)(bool oldValue, bool newValue); - -//Since Info Service contains only constant, only add method will be provided -void addInfoServiceToAccessory(Accessory *acc, string accName, string manufactuerName, string modelName, string serialNumber, identifyFunction identifyCallback); - -void handleAccessory(const char *request, unsigned int requestLen, char **reply, unsigned int *replyLen, connectionInfo *sender); - -void updateValueFromDeviceEnd(characteristics *c, int aid, int iid, string value); \ No newline at end of file +#pragma once +// +// PHKAccessory.h +// Workbench +// +// Created by Wai Man Chan on 9/27/14. +// +// + +#include +#include +#define __STDC_LIMIT_MACROS +#include +extern "C" { +#include +} + +#include "PHKNetworkIP.h" + +#include "PHKControllerRecord.h" + +extern "C" { +#include "PHKArduinoLightInterface.h" +} + +#include + +#if MCU +#else +#include +#endif + +using namespace std; + +typedef enum { + charType_adminOnlyAccess = 0x1, + charType_audioChannels = 0x2, + charType_audioCodexName = 0x3, + charType_audioCodexParameter= 0x4, + charType_audioFeedback = 0x5, + charType_audioPropAttr = 0x6, + charType_audioValAttr = 0x7, + charType_brightness = 0x8, + charType_cameraNightVision = 0x9, + charType_cameraPan = 0xA, + charType_cameraTilt = 0xB, + charType_cameraZoom = 0xC, + charType_coolingThreshold = 0xD, + charType_currentDoorState = 0xE, + charType_currentHeatCoolMode= 0xF, + charType_currentHumidity = 0x10, + charType_currentTemperature = 0x11, + charType_heatingThreshold = 0x12, + charType_hue = 0x13, + charType_identify = 0x14, + charType_inputVolume = 0x15, + charType_ipCameraStart = 0x16, + charType_ipCameraStop = 0x17, + charType_lockControlPoint = 0x19, + charType_lockAutoTimeout = 0x1A, + charType_lockLastAction = 0x1C, + charType_lockCurrentState = 0x1D, + charType_lockTargetState = 0x1E, + charType_logs = 0x1F, + charType_manufactuer = 0x20, + charType_modelName = 0x21, + charType_motionDetect = 0x22, + charType_serviceName = 0x23, + charType_obstruction = 0x24, + charType_on = 0x25, + charType_outletInUse = 0x26, + charType_outputVolume = 0x27, + charType_rotationDirection = 0x28, + charType_rotationSpeed = 0x29, + charType_rtcpExtProp = 0x2A, + charType_rtcpVideoPayload = 0x2B, + charType_rtcpAudioPayload = 0x2C, + charType_rtcpAudioClock = 0x2D, + charType_rtcpProtocol = 0x2E, + charType_saturation = 0x2F, + charType_serialNumber = 0x30, + charType_srtpCyptoSuite = 0x31, + charType_targetDoorState = 0x32, + charType_targetHeatCoolMode = 0x33, + charType_targetHumidity = 0x34, + charType_targetTemperature = 0x35, + charType_temperatureUnit = 0x36, + charType_version = 0x37, + charType_videoCodexName = 0x38, + charType_videoCodexPara = 0x39, + charType_videoMirror = 0x3A, + charType_videoPropAttr = 0x3B, + charType_videoRotation = 0x3C, + charType_videoValAttr = 0x3D, + +//#pragma - The following is only default by the device after iOS 9 + + charType_firmwareRevision = 0x52, + charType_hardwareRevision = 0x53, + charType_softwareRevision = 0x54, + + charType_reachable = 0x63, + + charType_airParticulateDensity = 0x64, + charType_airParticulateSize = 0x65, + charType_airQuality = 0x95, + charType_carbonDioxideDetected = 0x92, + charType_carbonMonoxideDetected = 0x69, + charType_carbonDioxideLevel = 0x93, + charType_carbonMonoxideLevel = 0x90, + charType_carbonDioxidePeakLevel = 0x94, + charType_carbonMonoxidePeakLevel = 0x91, + charType_smokeDetected = 0x76, + + charType_alarmCurrentState = 0x66, + charType_alarmTargetState = 0x67, + charType_batteryLevel = 0x68, + charType_contactSensorState = 0x6A, + charType_holdPosition = 0x6F, + charType_leakDetected = 0x70, + charType_occupancyDetected = 0x71, + + charType_currentAmbientLightLevel = 0x6B, + charType_currentHorizontalTiltAngle = 0x6C, + charType_targetHorizontalTiltAngle = 0x7B, + charType_currentPosition = 0x6D, + charType_targetPosition = 0x7C, + charType_currentVerticalTiltAngle = 0x6E, + charType_targetVerticalTiltAngle = 0x7D, + + charType_positionState = 0x72, + charType_programmableSwitchEvent = 0x73, + charType_programmableSwitchOutputState = 0x74, + + charType_sensorActive = 0x75, + charType_sensorFault = 0x77, + charType_sensorJammed = 0x78, + charType_sensorLowBattery = 0x79, + charType_sensorTampered = 0x7A, + charType_sensorChargingState= 0x8F, + + +//#pragma - The following is service provide + serviceType_accessoryInfo = 0x3E, + serviceType_camera = 0x3F, + serviceType_fan = 0x40, + serviceType_garageDoorOpener = 0x41, + serviceType_lightBulb = 0x43, + serviceType_lockManagement = 0x44, + serviceType_lockMechanism = 0x45, + serviceType_microphone = 0x46, + serviceType_outlet = 0x47, + serviceType_speaker = 0x48, + serviceType_switch = 0x49, + serviceType_thermostat = 0x4A, + + serviceType_alarmSystem = 0x7E, + serviceType_bridgingState = 0x62, + serviceType_carbonMonoxideSensor = 0x7F, + serviceType_contactSensor = 0x80, + serviceType_door = 0x81, + serviceType_humiditySensor = 0x82, + serviceType_leakSensor = 0x83, + serviceType_lightSensor = 0x84, + serviceType_motionSensor = 0x85, + serviceType_occupancySensor = 0x86, + serviceType_smokeSensor = 0x87, + serviceType_programmableSwitch_stateful = 0x88, + serviceType_programmableSwitch_stateless = 0x89, + serviceType_temperatureSensor = 0x8A, + serviceType_window = 0x8B, + serviceType_windowCover = 0x8C, + serviceType_airQualitySensor = 0x8C, + serviceType_securityAlarm = 0x8E, + serviceType_charging = 0x8F, + + serviceType_battery = 0x96, + serviceType_carbonDioxideSensor= 0x97, + +//#pragma - The following is for bluetooth characteristic + btCharType_pairSetup = 0x4C, + btCharType_pairVerify = 0x4E, + btCharType_pairingFeature = 0x4F, + btCharType_pairings = 0x50, + btCharType_serviceInstanceID = 0x51, +//#pragma - The following is for bluetooth service + btServiceType_accessoryInformation = 0xFED3, + btServiceType_camera = 0xFEC9, + btServiceType_fan = 0xFECB, + btServiceType_garageDoorOpener = 0xFECE, + btServiceType_lightBulb = 0xFED2, + btServiceType_lockManagement = 0xFECF, + btServiceType_lockMechanism = 0xFED0, + btServiceType_microphone = 0xFEC8, + btServiceType_outlet = 0xFECC, + btServiceType_speaker = 0xFEC7, + btServiceType_switch = 0xFECD, + +} charType; + +enum { + premission_read = 1, + premission_write = 1 << 1, + premission_notify = 1 << 2 //Notify = Accessory will notice the controller +}; + +typedef enum { + unit_none = 0, + unit_celsius, + unit_percentage, + unit_arcDegree +} unit; + + +class characteristics { +public: + + const unsigned short type; + const int premission; + int iid; + characteristics(unsigned short _type, int _premission): type(_type), premission(_premission) {} + virtual string value() = 0; + virtual void setValue(string str) = 0; + virtual string describe() = 0; + bool writable() { return premission&premission_write ? true : false ; } + bool notifiable() { return premission&premission_notify ? true : false; } +}; + +//To store value of device state, subclass the following type +class boolCharacteristics: public characteristics { +public: + bool _value; + void (*valueChangeFunctionCall)(bool oldValue, bool newValue); + boolCharacteristics(unsigned short _type, int _premission) + : valueChangeFunctionCall(NULL) + , characteristics(_type, _premission) + { + } + virtual string value() { + if (_value) + return "1"; + return "0"; + } + virtual void setValue(string str) { + bool newValue = false; + if (strncmp("true", str.c_str(), 4)==0 || strncmp("1", str.c_str(), 1)==0 ) + { + newValue = true; + } + if (valueChangeFunctionCall) + valueChangeFunctionCall(_value, newValue); + _value = newValue; + } + virtual string describe(); +}; + +class floatCharacteristics: public characteristics { +public: + float _value; + const float _minVal, _maxVal, _step; + const unit _unit; + void (*valueChangeFunctionCall)(float oldValue, float newValue); + floatCharacteristics(unsigned short _type, int _premission, float minVal, float maxVal, float step, unit charUnit) + : valueChangeFunctionCall(NULL) + ,characteristics(_type, _premission) + , _minVal(minVal) + , _maxVal(maxVal) + , _step(step) + , _unit(charUnit) + { + } + virtual string value() { + char temp[16]; + snprintf(temp, 16, "%f", _value); + return temp; + } + virtual void setValue(string str) { + float temp = (float) atof(str.c_str()); + if (temp == temp) { + if (valueChangeFunctionCall) + valueChangeFunctionCall(_value, temp); + _value = temp; + } + } + virtual string describe(); +}; + +class intCharacteristics: public characteristics { +public: + int _value; + const int _minVal, _maxVal, _step; + const unit _unit; + void (*valueChangeFunctionCall)(int oldValue, int newValue); + intCharacteristics(unsigned short _type, int _premission, int minVal, int maxVal, int step, unit charUnit) + : valueChangeFunctionCall(NULL) + , characteristics(_type, _premission) + , _minVal(minVal) + , _maxVal(maxVal) + , _step(step) + , _unit(charUnit) + { + _value = minVal; + } + virtual string value() { + char temp[16]; + snprintf(temp, 16, "%d", _value); + return temp; + } + virtual void setValue(string str) { + int temp = (int)atoi(str.c_str()); + if (temp == temp) { + if (valueChangeFunctionCall) + valueChangeFunctionCall(_value, (int)temp); + _value = (int) temp; + } + } + virtual string describe(); +}; + +class uint8Characteristics: public characteristics { +public: + int _value; + const int _minVal, _maxVal, _step; + const unit _unit; + void (*valueChangeFunctionCall)(int oldValue, int newValue); + uint8Characteristics(unsigned short _type, int _premission, int minVal, int maxVal, int step, unit charUnit) + : valueChangeFunctionCall(NULL) + , characteristics(_type, _premission) + , _minVal(minVal) + , _maxVal(maxVal) + , _step(step) + , _unit(charUnit) + { + _value = minVal; + } + virtual string value() { + char temp[16]; + snprintf(temp, 16, "%d", _value); + return temp; + } + virtual void setValue(string str) { + int temp = (int)atoi(str.c_str()); + if (temp == temp) { + if (valueChangeFunctionCall) + valueChangeFunctionCall(_value, (int)temp); + _value = (int) temp; + } + } + virtual string describe(); +}; + +class stringCharacteristics: public characteristics { +public: + string _value; + const unsigned short maxLen; + void (*valueChangeFunctionCall)(string oldValue, string newValue); + stringCharacteristics(unsigned short _type, int _premission, unsigned short _maxLen) + : valueChangeFunctionCall(NULL) + , characteristics(_type, _premission) + , maxLen(_maxLen) + { + } + virtual string value() { + return "\""+_value+"\""; + } + virtual void setValue(string str) { + if (valueChangeFunctionCall) + valueChangeFunctionCall(_value, str); + _value = str; + } + virtual string describe(); +}; + +//Abstract Layer of object +class Service { +public: + int serviceID, uuid; + vector _characteristics; + Service(int _uuid): uuid(_uuid) {} + virtual short numberOfCharacteristics() { return _characteristics.size(); } + virtual characteristics *characteristicsAtIndex(int index) { return _characteristics[index]; } + string describe(); +}; + +class Accessory { + int numberOfInstance; + vector_services; +public: + int aid; + void addService(Service *ser) { + ser->serviceID = ++numberOfInstance; + _services.push_back(ser); + } + void addCharacteristics(Service *ser, characteristics *cha) { + cha->iid = ++numberOfInstance; + ser->_characteristics.push_back(cha); + } + bool removeService(Service *ser) { + bool exist = false; + for (vector::iterator it = _services.begin(); it != _services.end(); it++) { + if (*it == ser) { + _services.erase(it); + exist = true; + } + } + delete ser; + return exist; + } + bool removeCharacteristics(characteristics *cha) { + bool exist = false; + for (vector::iterator it = _services.begin(); it != _services.end(); it++) { + for (vector::iterator jt = (*it)->_characteristics.begin(); jt != (*it)->_characteristics.end(); jt++) { + if (*jt == cha) { + (*it)->_characteristics.erase(jt); + exist = true; + } + } + } + delete cha; + return exist; + } + Accessory() : numberOfInstance (0) + { + } + virtual ~Accessory() + { + RemoveALL(); + } + short numberOfService() { return _services.size(); } + Service *serviceAtIndex(int index) { + for (vector::iterator it = _services.begin(); it != _services.end(); it++) { + if ((*it)->serviceID == index) { + return *it; + } + } + return NULL; + } + characteristics *characteristicsAtIndex(int index) { + for (vector::iterator it = _services.begin(); it != _services.end(); it++) { + for (vector::iterator jt = (*it)->_characteristics.begin(); jt != (*it)->_characteristics.end(); jt++) { + if ((*jt)->iid == index) { + return *jt; + } + } + } + return NULL; + } + string describe(); + void RemoveALL() + { + for (vector::iterator it = _services.begin(); it != _services.end(); it++) { + for (vector::iterator jt = (*it)->_characteristics.begin(); jt != (*it)->_characteristics.end(); jt++) { + delete *jt; + } + delete *it; + } + _services.clear(); + numberOfInstance = 0; + } +}; + + +class AccessorySet { +private: + vector _accessories; + int _aid; + pthread_mutex_t accessoryMutex; + AccessorySet() { + _aid = 0; + pthread_mutex_init(&accessoryMutex, NULL); + } + AccessorySet(AccessorySet const&); + void operator=(AccessorySet const&); +public: + static AccessorySet& getInstance() { + static AccessorySet instance; + + return instance; + } + void lock(); + void unlock(); + short numberOfAccessory() { + return (short) _accessories.size(); + } + Accessory *accessoryAtIndex(int index) { + for (vector::iterator it = _accessories.begin(); it != _accessories.end(); it++) { + if ((*it)->aid == index) { + return *it; + } + } + return NULL; + } + void addAccessory(Accessory *acc) { + acc->aid = ++_aid; + _accessories.push_back(acc); + } + bool removeAccessory(Accessory *acc) { + bool exist = false; + for (vector::iterator it = _accessories.begin(); it != _accessories.end(); it++) { + if (*it == acc) { + _accessories.erase(it); + exist = true; + } + } + delete acc; + return exist; + } + void RemoveALL() { + for (vector::iterator it = _accessories.begin(); it != _accessories.end(); it++) { + delete *it; + } + _accessories.clear(); + _aid = 0; + } + ~AccessorySet() { + pthread_mutex_destroy(&accessoryMutex); + RemoveALL(); + } + string describe(); + + ControllerRecord Controllers; +}; + +class AccessorySetAutoLock { +public: + AccessorySetAutoLock(){ + AccessorySet::getInstance().lock(); + } + + virtual ~AccessorySetAutoLock(){ + AccessorySet::getInstance().unlock(); + } +}; + +typedef void (*identifyFunction)(bool oldValue, bool newValue); + +//Since Info Service contains only constant, only add method will be provided +void addInfoServiceToAccessory(Accessory *acc, string accName, string manufactuerName, string modelName, string serialNumber, identifyFunction identifyCallback); + +void handleAccessory(const char *request, unsigned int requestLen, char **reply, unsigned int *replyLen, connectionInfo *sender); + +void updateValueFromDeviceEnd(characteristics *c, int aid, int iid, string value); + +//logger +typedef int(*PERSONAL_LOGGER_FUNCTION)(const char* msg,...); +extern PERSONAL_LOGGER_FUNCTION g_homekit_logger; +void Personal_homekit_set_logger_function(PERSONAL_LOGGER_FUNCTION); diff --git a/PHKArduinoLightInterface.c b/PHKArduinoLightInterface.c old mode 100644 new mode 100755 diff --git a/PHKArduinoLightInterface.h b/PHKArduinoLightInterface.h old mode 100644 new mode 100755 diff --git a/PHKControllerRecord.cpp b/PHKControllerRecord.cpp old mode 100644 new mode 100755 index 0580a77..cb05c4c --- a/PHKControllerRecord.cpp +++ b/PHKControllerRecord.cpp @@ -6,12 +6,9 @@ // // -#include "PHKControllerRecord.h" -#include "Configuration.h" #include #include - #if MCU #else #include @@ -19,19 +16,22 @@ using namespace std; -vectorreadIn(); -vectorcontrollerRecords = readIn(); +#include "PHKControllerRecord.h" +#include "Configuration.h" + -vectorreadIn() { + + + +void ControllerRecord::loadController() { ifstream fs; #if MCU #else - fs.open(controllerRecordsAddress, std::ifstream::in); + fs.open(this->storeFilePath.c_str(), std::ifstream::in); #endif - char buffer[70]; - bzero(buffer, 70); + char buffer[70] = {0}; PHKKeyRecord record; vector results; @@ -50,62 +50,67 @@ vectorreadIn() { #else fs.close(); #endif - - return results; + this->controllerRecords = results; } -void resetControllerRecord() { - ofstream fs; - fs.open(controllerRecordsAddress, std::ofstream::out|std::ofstream::trunc); +void ControllerRecord::resetController() { + unlink(this->storeFilePath.c_str() ); + this->controllerRecords.clear(); } -bool hasController() { - return controllerRecords.size() > 0; +bool ControllerRecord::hasController() { + return this->controllerRecords.size() > 0; } -void addControllerKey(PHKKeyRecord record) { - if (doControllerKeyExist(record) == false) { - controllerRecords.push_back(record); - +void ControllerRecord::storeFiles() +{ #if MCU #else - ofstream fs; - fs.open(controllerRecordsAddress, std::ofstream::trunc); + ofstream fs; + fs.open(this->storeFilePath.c_str(), std::ofstream::trunc); #endif - for (vector::iterator it = controllerRecords.begin(); it != controllerRecords.end(); it++) { + for (vector::iterator it = this->controllerRecords.begin(); it != this->controllerRecords.end(); it++) { #if MCU #else - fs.write(it->controllerID, 36); - fs.write(it->publicKey, 32); + fs.write(it->controllerID, 36); + fs.write(it->publicKey, 32); #endif - } - fs.close(); + } + fs.close(); +} + +void ControllerRecord::addControllerKey(PHKKeyRecord record) { + if (doControllerKeyExist(record) == false) { + this->controllerRecords.push_back(record); + storeFiles(); } } -bool doControllerKeyExist(PHKKeyRecord record) { - for (vector::iterator it = controllerRecords.begin(); it != controllerRecords.end(); it++) { +bool ControllerRecord::doControllerKeyExist(PHKKeyRecord record) { + for (vector::iterator it = this->controllerRecords.begin(); it != this->controllerRecords.end(); it++) { if (bcmp((*it).controllerID, record.controllerID, 32) == 0) return true; } return false; } -void removeControllerKey(PHKKeyRecord record) { - for (vector::iterator it = controllerRecords.begin(); it != controllerRecords.end(); it++) { +void ControllerRecord::removeControllerKey(PHKKeyRecord record) { + for (vector::iterator it = this->controllerRecords.begin(); it != this->controllerRecords.end(); it++) { if (bcmp((*it).controllerID, record.controllerID, 32) == 0) { - controllerRecords.push_back(record); + this->controllerRecords.erase(it); + storeFiles(); return; } } } -PHKKeyRecord getControllerKey(char key[32]) { - for (vector::iterator it = controllerRecords.begin(); it != controllerRecords.end(); it++) { +PHKKeyRecord ControllerRecord::getControllerKey(char key[32]) { + for (vector::iterator it = this->controllerRecords.begin(); it != this->controllerRecords.end(); it++) { if (bcmp(key, it->controllerID, 32) == 0) return *it; } PHKKeyRecord emptyRecord; bzero(emptyRecord.controllerID, 32); return emptyRecord; } + diff --git a/PHKControllerRecord.h b/PHKControllerRecord.h old mode 100644 new mode 100755 index c868e17..dda6cb1 --- a/PHKControllerRecord.h +++ b/PHKControllerRecord.h @@ -1,24 +1,45 @@ -#pragma once -// -// PHKControllerRecord.h -// Workbench -// -// Created by Wai Man Chan on 9/23/14. -// -// - -#include -#include -using namespace std; - -struct PHKKeyRecord { - char controllerID[36]; - char publicKey[32]; -}; - -void resetControllerRecord(); -bool hasController(); -void addControllerKey(PHKKeyRecord record); -bool doControllerKeyExist(PHKKeyRecord record); -void removeControllerKey(PHKKeyRecord record); -PHKKeyRecord getControllerKey(char key[32]); +#pragma once +// +// PHKControllerRecord.h +// Workbench +// +// Created by Wai Man Chan on 9/23/14. +// +// + +#include +#include +using namespace std; + +struct PHKKeyRecord { + char controllerID[36]; + char publicKey[32]; +}; + +class ControllerRecord +{ + string storeFilePath; + vector controllerRecords; + + void storeFiles(); + void loadController() ; +public: + ControllerRecord() + { + } + virtual ~ControllerRecord() + { + } + void create(const std::string& storeFilePath) + { + this->storeFilePath = storeFilePath; + loadController(); + } + + void resetController() ; + bool hasController() ; + void addControllerKey(PHKKeyRecord record) ; + bool doControllerKeyExist(PHKKeyRecord record) ; + void removeControllerKey(PHKKeyRecord record) ; + PHKKeyRecord getControllerKey(char key[32]) ; +}; diff --git a/PHKNetworkIP.cpp b/PHKNetworkIP.cpp old mode 100644 new mode 100755 index 8668226..c80038e --- a/PHKNetworkIP.cpp +++ b/PHKNetworkIP.cpp @@ -9,6 +9,8 @@ #include "PHKNetworkIP.h" #define PHKNetworkServiceType "_hap._tcp" + +#include #include #include #include @@ -59,26 +61,42 @@ using namespace std; #define portNumber 0 -#if MCU -#else connectionInfo connection[numberOfClient]; -#endif const unsigned char modulusStr[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, 0xCA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; const unsigned char curveBasePoint[] = { 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; const unsigned char generator[] = {0x05}; -char tempStr[3073]; const unsigned char accessorySecretKey[32] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74}; -int _socket_v4, _socket_v6; -DNSServiceRef netServiceV4, netServiceV6; +static std::string g_DeviceName; +static std::string g_PinCode; +static std::string g_DeviceIdentity; + +static int _socket_v4 = -1; +static DNSServiceRef netServiceV4; +#ifdef _WIN32 +#else +static int _socket_v6 = -1; +static DNSServiceRef netServiceV6; +#endif deviceType currentDeviceType = deviceType_other; -int currentConfigurationNum = 1; +static int g_currentConfigurationNum = 1; + +void write204(int sock) { + char *reply = new char[1024]; + int len = + snprintf(reply, 1024, + "HTTP/1.1 204 No Content\r\nContent-Type: application/hap+json\r\nContent-Length: 0\r\n\r\n"); + + write(sock, reply, len); + delete[] reply; + +} int is_big_endian(void) { @@ -97,13 +115,16 @@ int setupSocketV4(unsigned int maximumConnection) { addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_family = PF_INET; addr.sin_port = htons(portNumber); int optval = 1; socklen_t optlen = sizeof(optval); - setsockopt(_socket, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen); + setsockopt(_socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&optval, optlen); bind(_socket, (const struct sockaddr *)&addr, sizeof(addr)); listen(_socket, maximumConnection); - return _socket; + + return _socket; } +#ifdef _WIN32 +#else int setupSocketV6(unsigned int maximumConnection) { int _socket = socket(PF_INET6, SOCK_STREAM, 0); sockaddr_in6 addr; bzero(&addr, sizeof(addr)); @@ -112,6 +133,7 @@ int setupSocketV6(unsigned int maximumConnection) { listen(_socket, maximumConnection); return _socket; } +#endif unsigned short getSocketPortNumberV4(int _socket) { sockaddr_in addr; socklen_t len = sizeof(addr); @@ -119,15 +141,18 @@ unsigned short getSocketPortNumberV4(int _socket) { return ntohs(addr.sin_port); } +#ifdef _WIN32 +#else unsigned short getSocketPortNumberV6(int _socket) { sockaddr_in6 addr; socklen_t len = sizeof(addr); getsockname(_socket, (struct sockaddr *)&addr, &len); return ntohs(addr.sin6_port); } +#endif void registerFail(DNSServiceRef sdRef, DNSRecordRef RecordRef, DNSServiceFlags flags, DNSServiceErrorType errorCode, void *context ) { #if HomeKitLog == 1 - printf("Service can't register\n"); + g_homekit_logger("Service can't register\n"); #endif exit(0); } @@ -136,41 +161,56 @@ TXTRecordRef buildTXTRecord() { TXTRecordRef txtRecord; TXTRecordCreate(&txtRecord, 0, NULL); TXTRecordSetValue(&txtRecord, "pv", 3, "1.0"); //Version - TXTRecordSetValue(&txtRecord, "id", 17, deviceIdentity); //Device id - char buf[3]; - sprintf(buf, "%d", currentConfigurationNum); - TXTRecordSetValue(&txtRecord, "c#", 1, buf); //Configuration Number - TXTRecordSetValue(&txtRecord, "s#", 1, "4"); //Number of service - if (hasController()) buf[0] = '0'; + TXTRecordSetValue(&txtRecord, "id", 17, g_DeviceIdentity.c_str() ); //Device id + + char buf[10]; + snprintf(buf,10, "%d", g_currentConfigurationNum); + TXTRecordSetValue(&txtRecord, "c#", strlen(buf), buf); //Configuration Number + TXTRecordSetValue(&txtRecord, "s#", 1, "1"); //Number of service + + if (AccessorySet::getInstance().Controllers.hasController()) buf[0] = '0'; else buf[0] = '1'; TXTRecordSetValue(&txtRecord, "sf", 1, buf); //Discoverable: 0 if has been paired - TXTRecordSetValue(&txtRecord, "ff", 1, "0"); //1 for MFI product - TXTRecordSetValue(&txtRecord, "md", strlen(deviceName), deviceName); //Model Name - int len = sprintf(buf, "%d", currentDeviceType); + + TXTRecordSetValue(&txtRecord, "ff", 1, "0"); //1 for MFI product + TXTRecordSetValue(&txtRecord, "md", g_DeviceName.size(), g_DeviceName.c_str() ); //Model Name + + int len = sprintf(buf, "%d", currentDeviceType); TXTRecordSetValue(&txtRecord, "ci", len, buf); //1 for MFI product return txtRecord; } void updateConfiguration() { - currentConfigurationNum++; + g_currentConfigurationNum++; TXTRecordRef txtRecord = buildTXTRecord(); DNSServiceUpdateRecord(netServiceV4, NULL, 0, TXTRecordGetLength(&txtRecord), TXTRecordGetBytesPtr(&txtRecord), 0); TXTRecordDeallocate(&txtRecord); } void PHKNetworkIP::setupSocket() { +#if HomeKitLog == 1 + g_homekit_logger("PHKNetworkIP::setupSocket\n"); +#endif TXTRecordRef txtRecord = buildTXTRecord(); _socket_v4 = setupSocketV4(5); - DNSServiceRegister(&netServiceV4, 0, 0, deviceName, PHKNetworkServiceType, "", NULL, htons(getSocketPortNumberV4(_socket_v4)), TXTRecordGetLength(&txtRecord), TXTRecordGetBytesPtr(&txtRecord), NULL, NULL); - TXTRecordDeallocate(&txtRecord); + + DNSServiceRegister(&netServiceV4, 0, 0, g_DeviceName.c_str() , PHKNetworkServiceType, "", NULL, htons(getSocketPortNumberV4(_socket_v4)), TXTRecordGetLength(&txtRecord), TXTRecordGetBytesPtr(&txtRecord), NULL, NULL); + + TXTRecordDeallocate(&txtRecord); } -PHKNetworkIP::PHKNetworkIP() { - SRP_initialize_library(); - srand((unsigned int)time(NULL)); - for (int i = 0; i < numberOfClient; i++) { - connection[i].subSocket = -1; - } +PHKNetworkIP::PHKNetworkIP(const string& name,const string& pinCode,const string& identity,const string& controllerRecordsPath) { + g_DeviceName = name; + g_PinCode = pinCode; + g_DeviceIdentity = identity; + AccessorySet::getInstance().Controllers.create(controllerRecordsPath); + + for(int i = 0 ; i < numberOfClient; i++ ) + { + connection[i].init(); + } + SRP_initialize_library(); + setupSocket(); } @@ -178,7 +218,7 @@ PHKNetworkIP::PHKNetworkIP() { void broadcastMessage(void *sender, char *resultData, size_t resultLen) { #if HomeKitLog == 1 - printf("Broadcast with sender\n"); + g_homekit_logger("Broadcast with sender\n"); #endif for (int i = 0; i < numberOfClient; i++) { @@ -187,11 +227,12 @@ void broadcastMessage(void *sender, char *resultData, size_t resultLen) { pthread_mutex_lock(&connection[i].mutex); - chacha20_ctx chacha20; bzero(&chacha20, sizeof(chacha20)); + chacha20_ctx chacha20 = {0}; - char temp[64]; bzero(temp, 64); char temp2[64]; bzero(temp2, 64); + char temp[64] = {0}; char temp2[64] = {0}; - char *reply = new char[resultLen+18]; + vector _reply_vec(resultLen+18); + char *reply = &_reply_vec[0]; reply[0] = resultLen%256; reply[1] = (resultLen-(uint8_t)reply[0])/256; @@ -205,8 +246,7 @@ void broadcastMessage(void *sender, char *resultData, size_t resultLen) { poly1305_context verifyContext; bzero(&verifyContext, sizeof(verifyContext)); poly1305_init(&verifyContext, (const unsigned char*)temp2); { - char waste[16]; - bzero(waste, 16); + char waste[16] = {0}; poly1305_update(&verifyContext, (const unsigned char *)reply, 2); poly1305_update(&verifyContext, (const unsigned char *)waste, 14); @@ -221,14 +261,12 @@ void broadcastMessage(void *sender, char *resultData, size_t resultLen) { } poly1305_finish(&verifyContext, (unsigned char*)&reply[resultLen+2]); #else - char verify[16]; - memset(verify, 0, 16); + char verify[16] = {0}; Poly1305_GenKey((const unsigned char *)temp2, (uint8_t *)reply, resultLen, Type_Data_With_Length, verify); memcpy((unsigned char*)&reply[resultLen+2], verify, 16); #endif - write(socketNumber, reply, resultLen+18); - delete [] reply; + send(socketNumber, reply, resultLen+18,0); pthread_mutex_unlock(&connection[i].mutex); } } @@ -238,17 +276,17 @@ void *connectionLoop(void *threadInfo) { int subSocket = info->subSocket; ssize_t len; if (subSocket >= 0) { #if HomeKitLog == 1 - printf("Start Connect: %d\n", subSocket); + g_homekit_logger("Start Connect: %d\n", subSocket); #endif do { - len = read(subSocket, info->buffer, 4096); + len = recv(subSocket, info->buffer, 4096,0); #if HomeKitLog == 1 - printf("Return len %d for socket %d\n", len, subSocket); + g_homekit_logger("Return len %d for socket %d\n", len, subSocket); #endif #if HomeKitReplyHeaderLog == 1 - printf("Message: %s\n", info->buffer); + g_homekit_logger("Message: %s\n", info->buffer); #endif PHKNetworkMessage msg(info->buffer); @@ -269,25 +307,54 @@ void *connectionLoop(void *threadInfo) { info->handleAccessoryRequest(); } else if (!strcmp(msg.directory, "identify")){ - close(subSocket); + write204(subSocket); +#ifdef _WIN32 + closesocket(subSocket); +#else + close(subSocket); +#endif } } } while (len > 0); - + +#ifdef _WIN32 + ::closesocket(subSocket); +#else close(subSocket); +#endif #if HomeKitLog == 1 - printf("Stop Connect: %d\n", subSocket); + g_homekit_logger("Stop Connect: %d\n", subSocket); #endif info->subSocket = -1; } - return NULL; + + pthread_detach(info->thread); + return NULL; +} + +void PHKNetworkIP::closeAcceptConnection(){ + + if (_socket_v4 >= 0) + { +#ifdef _WIN32 + closesocket(_socket_v4); +#else + shutdown(_socket_v4,SHUT_RDWR); + close(_socket_v4); +#endif + _socket_v4 = -1; + } } void PHKNetworkIP::handleConnection() const { int subSocket = accept(_socket_v4, 0, NULL); + if (subSocket < 0) + { + return ; + } int index = -1; for (int i = 0; i < numberOfClient; i++) { @@ -300,7 +367,14 @@ void PHKNetworkIP::handleConnection() const { } } - if (index < 0) close(subSocket); + if (index < 0) + { +#ifdef _WIN32 + closesocket(subSocket); +#else + close(subSocket); +#endif + } } @@ -311,7 +385,9 @@ void PHKNetworkIP::handleConnection() const { //Passed-in buf is len and data_buf void connectionInfo::Poly1305_GenKey(const unsigned char * key, uint8_t * buf, uint16_t len, Poly1305Type_t type, char* verify) { - printf("Length: %d\n", buf[0]); +#if HomeKitLog == 1 + g_homekit_logger("Length: %d\n", buf[0]); +#endif if (key == NULL || buf == NULL || len < 2 || verify == NULL) return; @@ -344,7 +420,7 @@ void connectionInfo::Poly1305_GenKey(const unsigned char * key, uint8_t * buf, u poly1305_update(&verifyContext, (const unsigned char *)&_len, 1); poly1305_update(&verifyContext, (const unsigned char *)&waste, 7); - _len = len; + _len = (unsigned char)len; poly1305_update(&verifyContext, (const unsigned char *)&_len, 1); _len = len/256; @@ -378,7 +454,7 @@ void connectionInfo::handlePairSeup() { switch (state) { case State_M1_SRPStartRequest: { #if HomeKitLog == 1 - printf("%s, %d: State_M1_SRPStartRequest\n", __func__, __LINE__); + g_homekit_logger("%s, %d: State_M1_SRPStartRequest\n", __func__, __LINE__); #endif PHKNetworkMessageDataRecord saltRec; PHKNetworkMessageDataRecord publicKeyRec; @@ -391,7 +467,7 @@ void connectionInfo::handlePairSeup() { SRP_RESULT result = SRP_set_username(srp, "Pair-Setup"); int modulusSize = sizeof(modulusStr) / sizeof(modulusStr[0]); result = SRP_set_params(srp, (const unsigned char *)modulusStr, modulusSize, (const unsigned char *)generator, 1, saltChar, 16); - result = SRP_set_auth_password(srp, devicePassword); + result = SRP_set_auth_password(srp, g_PinCode.c_str() ); result = SRP_gen_pub(srp, &publicKey); saltRec.index = 2; @@ -412,7 +488,7 @@ void connectionInfo::handlePairSeup() { break; case State_M3_SRPVerifyRequest: { #if HomeKitLog == 1 - printf("%s, %d: State_M3_SRPVerifyRequest\n", __func__, __LINE__); + g_homekit_logger("%s, %d: State_M3_SRPVerifyRequest\n", __func__, __LINE__); #endif const char *keyStr = 0; int keyLen = 0; @@ -438,7 +514,7 @@ void connectionInfo::handlePairSeup() { responseRecord.length = 1; mResponse.data.addRecord(responseRecord); #if HomeKitLog == 1 - printf("Oops at M3\n"); + g_homekit_logger("Oops at M3\n"); #endif } else { SRP_respond(srp, &response); @@ -450,19 +526,26 @@ void connectionInfo::handlePairSeup() { bcopy(response->data, responseRecord.data, responseRecord.length); mResponse.data.addRecord(responseRecord); #if HomeKitLog == 1 - printf("Password Correct\n"); + g_homekit_logger("Password Correct\n"); #endif } const char salt[] = "Pair-Setup-Encrypt-Salt"; const char info[] = "Pair-Setup-Encrypt-Info"; int i = hkdf((const unsigned char*)salt, strlen(salt), (const unsigned char*)secretKey->data, secretKey->length, (const unsigned char*)info, strlen(info), (uint8_t*)sessionKey, 32); - if (i != 0) return; + if (i != 0) + { +#if HomeKitLog == 1 + g_homekit_logger("hkdf result zero\n"); +#endif + SRP_free(srp); + return; + } } break; case State_M5_ExchangeRequest: { #if HomeKitLog == 1 - printf("%s, %d: State_M5_ExchangeRequest\n", __func__, __LINE__); + g_homekit_logger("%s, %d: State_M5_ExchangeRequest\n", __func__, __LINE__); #endif const char *encryptedPackage = NULL;int packageLen = 0; @@ -477,13 +560,14 @@ void connectionInfo::handlePairSeup() { chacha20_setup(&chacha20, (const uint8_t *)sessionKey, 32, (uint8_t *)"PS-Msg05"); //Ploy1305 key - char temp[64]; bzero(temp, 64); char temp2[64]; bzero(temp2, 64); + char temp[64] = {0}; char temp2[64] = {0}; chacha20_encrypt(&chacha20, (const uint8_t*)temp, (uint8_t *)temp2, 64); - char verify[16]; bzero(verify, 16); + char verify[16] = {0}; Poly1305_GenKey((const unsigned char*)temp2, (unsigned char *)encryptedData, packageLen - 16, Type_Data_Without_Length, verify); - char *decryptedData = new char[packageLen-16]; + vector decryptedData_vec(packageLen-16); + char *decryptedData = &decryptedData_vec[0]; bzero(decryptedData, packageLen-16); chacha20_decrypt(&chacha20, (const uint8_t *)encryptedData, (uint8_t *)decryptedData, packageLen-16); @@ -498,20 +582,20 @@ void connectionInfo::handlePairSeup() { #if HomeKitLog == 1 for(int j = 0; j < packageLen-16; j++) - printf("%X ", decryptedData[j]); - printf("\n"); + g_homekit_logger("%X ", decryptedData[j]); + g_homekit_logger("\n"); - printf("verify: "); + g_homekit_logger("verify: "); for(int j = 0; j < 16; j++) - printf("%X ", verify[j]); - printf("\n"); + g_homekit_logger("%X ", verify[j]); + g_homekit_logger("\n"); - printf("mac: "); + g_homekit_logger("mac: "); for(int j = 0; j < 16; j++) - printf("%X ", mac[j]); - printf("\n"); + g_homekit_logger("%X ", mac[j]); + g_homekit_logger("\n"); - printf("Corrupt TLv8 at M5\n"); + g_homekit_logger("Corrupt TLv8 at M5\n"); #endif } else { /* @@ -526,12 +610,20 @@ void connectionInfo::handlePairSeup() { PHKKeyRecord newRecord; bcopy(controllerIdentifier, newRecord.controllerID, 36); bcopy(controllerPublicKey, newRecord.publicKey, 32); - addControllerKey(newRecord); + AccessorySet::getInstance().Controllers.addControllerKey(newRecord); const char salt[] = "Pair-Setup-Controller-Sign-Salt"; const char info[] = "Pair-Setup-Controller-Sign-Info"; int i = hkdf((const unsigned char*)salt, strlen(salt), (const unsigned char*)secretKey->data, secretKey->length, (const unsigned char*)info, strlen(info), (uint8_t*)controllerHash, 32); - if (i != 0) return; + if (i != 0) + { +#if HomeKitLog == 1 + g_homekit_logger("hkdf result zero (2)\n"); +#endif + delete subTLV8; + SRP_free(srp); + return; + } bcopy(controllerIdentifier, &controllerHash[32], 36); bcopy(controllerPublicKey, &controllerHash[68], 32); @@ -539,13 +631,20 @@ void connectionInfo::handlePairSeup() { int ed25519_err = ed25519_sign_open((const unsigned char*)controllerHash, 100, (const unsigned char*)controllerPublicKey, (const unsigned char*)controllerSignature); delete subTLV8; - if (ed25519_err) return; + if (ed25519_err) + { +#if HomeKitLog == 1 + g_homekit_logger("ed25519_sign_open error %d\n",ed25519_err); +#endif + SRP_free(srp); + return; + } else { PHKNetworkMessageData *returnTLV8 = new PHKNetworkMessageData(); { PHKNetworkMessageDataRecord usernameRecord; - usernameRecord.activate = true; usernameRecord.index = 1; usernameRecord.length = strlen(deviceIdentity); usernameRecord.data = new char[usernameRecord.length]; bcopy(deviceIdentity, usernameRecord.data, usernameRecord.length); + usernameRecord.activate = true; usernameRecord.index = 1; usernameRecord.length = g_DeviceIdentity.size(); usernameRecord.data = new char[usernameRecord.length]; bcopy(g_DeviceIdentity.c_str(), usernameRecord.data, usernameRecord.length); returnTLV8->addRecord(usernameRecord); } @@ -558,7 +657,7 @@ void connectionInfo::handlePairSeup() { uint8_t output[150]; hkdf((const unsigned char*)salt, strlen(salt), (const unsigned char*)secretKey->data, secretKey->length, (const unsigned char*)info, strlen(info), output, 32); - bcopy(deviceIdentity, &output[32], strlen(deviceIdentity)); + bcopy(g_DeviceIdentity.c_str() , &output[32], g_DeviceIdentity.size() ); char *signature = new char[64]; ed25519_secret_key edSecret; @@ -566,8 +665,8 @@ void connectionInfo::handlePairSeup() { ed25519_public_key edPubKey; ed25519_publickey(edSecret, edPubKey); - bcopy(edPubKey, &output[32+strlen(deviceIdentity)], 32); - ed25519_sign(output, 64+strlen(deviceIdentity), (const unsigned char*)edSecret, (const unsigned char*)edPubKey, (unsigned char *)signature); + bcopy(edPubKey, &output[32+g_DeviceIdentity.size()], 32); + ed25519_sign(output, 64+g_DeviceIdentity.size(), (const unsigned char*)edSecret, (const unsigned char*)edPubKey, (unsigned char *)signature); PHKNetworkMessageDataRecord signatureRecord; signatureRecord.activate = true; signatureRecord.data = signature; signatureRecord.index = 10; signatureRecord.length = 64; returnTLV8->addRecord(signatureRecord); @@ -592,14 +691,15 @@ void connectionInfo::handlePairSeup() { chacha20_ctx ctx; bzero(&ctx, sizeof(ctx)); chacha20_setup(&ctx, (const uint8_t *)sessionKey, 32, (uint8_t *)"PS-Msg06"); - char buffer[64], key[64]; bzero(buffer, 64); + char buffer[64] = {0}, key[64]; chacha20_encrypt(&ctx, (const uint8_t *)buffer, (uint8_t *)key, 64); chacha20_encrypt(&ctx, (const uint8_t *)tlv8Data, (uint8_t *)tlv8Record.data, tlv8Len); + delete [] tlv8Data; - char verify[16]; - memset(verify, 0, 16); + char verify[16] = {0}; Poly1305_GenKey((const unsigned char *)key, (unsigned char*)tlv8Record.data, tlv8Len, Type_Data_Without_Length, verify); memcpy((unsigned char *)&tlv8Record.data[tlv8Len], verify, 16); + } tlv8Record.activate = true; tlv8Record.index = 5; @@ -613,11 +713,12 @@ void connectionInfo::handlePairSeup() { mResponse.data.addRecord(stateRecord); mResponse.getBinaryPtr(&responseBuffer, &responseLen); if (responseBuffer) { - write(subSocket, (const void *)responseBuffer, (size_t)responseLen); + send(subSocket, responseBuffer, (size_t)responseLen,0); delete [] responseBuffer; } delete []encryptedData; + SRP_free(srp); return; } @@ -627,20 +728,20 @@ void connectionInfo::handlePairSeup() { mResponse.getBinaryPtr(&responseBuffer, &responseLen); if (responseBuffer) { #if HomeKitLog == 1 - printf("%s, %d, responseBuffer = %s, responseLen = %d\n", __func__, __LINE__, responseBuffer, responseLen); + g_homekit_logger("%s, %d, responseBuffer = %s, responseLen = %d\n", __func__, __LINE__, responseBuffer, responseLen); #endif - int len = write(subSocket, (const void *)responseBuffer, (size_t)responseLen); + int len = send(subSocket, responseBuffer, (size_t)responseLen,0); delete [] responseBuffer; #if HomeKitLog == 1 - printf("Pair Setup Transfered length %d\n", len); + g_homekit_logger("Pair Setup Transfered length %d\n", len); #endif } else { #if HomeKitLog == 1 - printf("Why empty response\n"); + g_homekit_logger("Why empty response\n"); #endif } - } while (read(subSocket, (void *)buffer, 4096) > 0); + } while (recv(subSocket, buffer, 4096,0) > 0); SRP_free(srp); } @@ -655,7 +756,7 @@ void connectionInfo::handlePairVerify() { uint8_t enKey[32]; #if HomeKitLog == 1 - printf("Start Pair Verify\n"); + g_homekit_logger("Start Pair Verify\n"); #endif do { @@ -665,7 +766,7 @@ void connectionInfo::handlePairVerify() { switch (state) { case State_Pair_Verify_M1: { #if HomeKitLog == 1 - printf("Pair Verify M1\n"); + g_homekit_logger("Pair Verify M1\n"); #endif bcopy(msg.data.dataPtrForIndex(3), controllerPublicKey, 32); for (short i = 0; i < sizeof(secretKey); i++) { @@ -674,11 +775,12 @@ void connectionInfo::handlePairVerify() { curve25519_donna((u8*)publicKey, (const u8 *)secretKey, (const u8 *)curveBasePoint); curve25519_donna(sharedKey, secretKey, controllerPublicKey); - - char *temp = new char[100]; + + vector _temp_vec(100); + char *temp = &_temp_vec[0]; bcopy(publicKey, temp, 32); - bcopy(deviceIdentity, &temp[32], strlen(deviceIdentity)); - bcopy(controllerPublicKey, &temp[32+strlen(deviceIdentity)], 32); + bcopy(g_DeviceIdentity.c_str(), &temp[32], g_DeviceIdentity.size()); + bcopy(controllerPublicKey, &temp[32+g_DeviceIdentity.size()], 32); PHKNetworkMessageDataRecord signRecord; signRecord.activate = true; signRecord.data = new char[64]; signRecord.index = 10; signRecord.length = 64; @@ -688,13 +790,12 @@ void connectionInfo::handlePairVerify() { ed25519_public_key edPubKey; ed25519_publickey(edSecret, edPubKey); - ed25519_sign((const unsigned char *)temp, 64+strlen(deviceIdentity), edSecret, edPubKey, (unsigned char *)signRecord.data); - delete [] temp; + ed25519_sign((const unsigned char *)temp, 64+g_DeviceIdentity.size(), edSecret, edPubKey, (unsigned char *)signRecord.data); PHKNetworkMessageDataRecord idRecord; idRecord.activate = true; idRecord.data = new char[17]; - bcopy(deviceIdentity, idRecord.data, 17); + bcopy(g_DeviceIdentity.c_str() , idRecord.data, 17); idRecord.index = 1; idRecord.length = (unsigned int)17; @@ -717,10 +818,12 @@ void connectionInfo::handlePairVerify() { const char *plainMsg = 0; unsigned short msgLen = 0; data.rawData(&plainMsg, &msgLen); - char *encryptMsg = new char[msgLen+16]; - char *polyKey = new char[64]; bzero(polyKey, 64); + vector _encryptMsg_vec(msgLen+16); + vector _polyKey_vec(msgLen+16); + char *encryptMsg = &_encryptMsg_vec[0]; + char polyKey[64] = {0}; - char zero[64]; bzero(zero, 64); + char zero[64] = {0}; chacha20_ctx chacha; chacha20_setup(&chacha, enKey, 32, (uint8_t *)"PV-Msg02"); @@ -729,8 +832,7 @@ void connectionInfo::handlePairVerify() { delete [] plainMsg; - char verify[16]; - memset(verify, 0, 16); + char verify[16] = {0}; Poly1305_GenKey((const unsigned char *)polyKey, (uint8_t *)encryptMsg, msgLen, Type_Data_Without_Length, verify); memcpy((unsigned char *)&encryptMsg[msgLen], verify, 16); @@ -742,33 +844,32 @@ void connectionInfo::handlePairVerify() { bcopy(encryptMsg, encryptRecord.data, encryptRecord.length); response.data.addRecord(encryptRecord); - delete [] encryptMsg; - delete [] polyKey; } break; case State_Pair_Verify_M3: { #if HomeKitLog == 1 - printf("Pair Verify M3\n"); + g_homekit_logger("Pair Verify M3\n"); #endif char *encryptedData = msg.data.dataPtrForIndex(5); short packageLen = msg.data.lengthForIndex(5); - chacha20_ctx chacha20; bzero(&chacha20, sizeof(chacha20)); + chacha20_ctx chacha20 = {0}; chacha20_setup(&chacha20, (const uint8_t *)enKey, 32, (uint8_t *)"PV-Msg03"); //Ploy1305 key - char temp[64]; bzero(temp, 64); char temp2[64]; bzero(temp2, 64); + char temp[64] = {0}; char temp2[64] = {0}; chacha20_encrypt(&chacha20, (const uint8_t*)temp, (uint8_t *)temp2, 64); - char verify[16]; bzero(verify, 16); + char verify[16] = {0}; Poly1305_GenKey((const unsigned char *)temp2, (uint8_t *)encryptedData, packageLen - 16, Type_Data_Without_Length, verify); if (!bcmp(verify, &encryptedData[packageLen-16], 16)) { - char *decryptData = new char[packageLen-16]; + vector decryptData_vec(packageLen-16); + char *decryptData = &decryptData_vec[0]; chacha20_decrypt(&chacha20, (const uint8_t *)encryptedData, (uint8_t *)decryptData, packageLen-16); PHKNetworkMessageData data = PHKNetworkMessageData(decryptData, packageLen-16); - PHKKeyRecord rec = getControllerKey(data.dataPtrForIndex(1)); + PHKKeyRecord rec = AccessorySet::getInstance().Controllers.getControllerKey(data.dataPtrForIndex(1)); char tempMsg[100]; bcopy(controllerPublicKey, tempMsg, 32); @@ -785,7 +886,7 @@ void connectionInfo::handlePairVerify() { hkdf((uint8_t *)"Control-Salt", 12, sharedKey, 32, (uint8_t *)"Control-Write-Encryption-Key", 28, controllerToAccessoryKey, 32); #if HomeKitLog == 1 - printf("Verify success\n"); + g_homekit_logger("Verify success\n"); #endif } else { @@ -797,11 +898,10 @@ void connectionInfo::handlePairVerify() { error.length = 1; response.data.addRecord(error); #if HomeKitLog == 1 - printf("Verify failed\n"); + g_homekit_logger("Verify failed\n"); #endif } - delete [] decryptData; } } @@ -818,22 +918,23 @@ void connectionInfo::handlePairVerify() { char *repBuffer = 0; int repLen = 0; response.getBinaryPtr(&repBuffer, &repLen); if (repBuffer) { - write(subSocket, repBuffer, repLen); + send(subSocket, repBuffer, repLen,0); delete [] repBuffer; } - } while (!end && read(subSocket, buffer, 4096) > 0); + } while (!end && recv(subSocket, buffer, 4096,0) > 0); } void connectionInfo::handleAccessoryRequest() { connected = true; - - char *decryptData = new char[2048]; + + vector decryptData_vec(2048); + char *decryptData = &decryptData_vec[0]; int len; #if HomeKitLog == 1 - printf("Successfully Connect\n"); + g_homekit_logger("Successfully Connect\n"); #endif numberOfMsgRec = 0; @@ -845,7 +946,7 @@ void connectionInfo::handleAccessoryRequest() { do { bzero(buffer, 4096); - len = read(subSocket, buffer, 4096); + len = recv(subSocket, buffer, 4096,0); //FIXME make sure buffer len > (2 + msgLen + 16)?? if (len > 0) { @@ -853,50 +954,57 @@ void connectionInfo::handleAccessoryRequest() { chacha20_ctx chacha20; bzero(&chacha20, sizeof(chacha20)); - printf("send: %llx\n", numberOfMsgRec); - if (!is_big_endian()) numberOfMsgRec = bswap_64(numberOfMsgRec); - printf("send: %llx\n", numberOfMsgRec); - chacha20_setup(&chacha20, (const uint8_t *)controllerToAccessoryKey, 32, (uint8_t *)&numberOfMsgRec); +#if HomeKitLog == 1 + g_homekit_logger("send: %llx\n", numberOfMsgRec); +#endif + if (!is_big_endian()) numberOfMsgRec = bswap_64(numberOfMsgRec); +#if HomeKitLog == 1 + g_homekit_logger("send: %llx\n", numberOfMsgRec); +#endif + chacha20_setup(&chacha20, (const uint8_t *)controllerToAccessoryKey, 32, (uint8_t *)&numberOfMsgRec); if (!is_big_endian()) numberOfMsgRec = bswap_64(numberOfMsgRec); numberOfMsgRec++; - printf("send: %llx\n", numberOfMsgRec); - - char temp[64]; bzero(temp, 64); char temp2[64]; bzero(temp2, 64); +#if HomeKitLog == 1 + g_homekit_logger("send: %llx\n", numberOfMsgRec); +#endif + char temp[64] = {0}; char temp2[64] = {0}; chacha20_encrypt(&chacha20, (const uint8_t*)temp, (uint8_t *)temp2, 64); //Ploy1305 key - char verify[16]; bzero(verify, 16); + char verify[16] = {0}; Poly1305_GenKey((const unsigned char *)temp2, (uint8_t *)buffer, msgLen, Type_Data_With_Length, verify); bzero(decryptData, 2048); chacha20_encrypt(&chacha20, (const uint8_t *)&buffer[2], (uint8_t *)decryptData, msgLen); - printf("Request: %s\nPacketLen: %d\n, MessageLen: %d\n", decryptData, len, strlen(decryptData)); +#if HomeKitLog == 1 + g_homekit_logger("Request: %s\nPacketLen: %d\n, MessageLen: %d\n", decryptData, len, strlen(decryptData)); +#endif if(len >= (2 + msgLen + 16) && memcmp((void *)verify, (void *)&buffer[2 + msgLen], 16) == 0) { #if HomeKitLog == 1 - printf("Verify successfully!\n"); + g_homekit_logger("Verify successfully!\n"); #endif } else { #if HomeKitLog == 1 - printf("Passed-in data is no-verified!\n"); + g_homekit_logger("Passed-in data is no-verified!\n"); for (int i = 0; i < 16; i++) - printf("%ud ", verify[i]); - printf("\n"); + g_homekit_logger("%ud ", verify[i]); + g_homekit_logger("\n"); for (int i = 0; i < 16; i++) - printf("%ud ", buffer[2 + msgLen+i]); - printf("\n"); + g_homekit_logger("%ud ", buffer[2 + msgLen+i]); + g_homekit_logger("\n"); unsigned long long numberOfMsgRec_ = numberOfMsgRec-1; chacha20_setup(&chacha20, (const uint8_t *)controllerToAccessoryKey, 32, (uint8_t *)&numberOfMsgRec_); chacha20_encrypt(&chacha20, (const uint8_t*)temp, (uint8_t *)temp2, 64); Poly1305_GenKey((const unsigned char *)temp, (uint8_t *)buffer, msgLen, Type_Data_With_Length, verify); for (int i = 0; i < 16; i++) - printf("%ud ", verify[i]); - printf("\n"); + g_homekit_logger("%ud ", verify[i]); + g_homekit_logger("\n"); #endif continue; @@ -909,7 +1017,8 @@ void connectionInfo::handleAccessoryRequest() { handleAccessory(decryptData, msgLen, &resultData, &resultLen, this); //18 = 2(resultLen) + 16(poly1305 verify key) - char *reply = new char[resultLen+18]; + vector reply_vec(resultLen+18); + char *reply = &reply_vec[0]; reply[0] = resultLen%256; reply[1] = (resultLen-(uint8_t)reply[0])/256; @@ -924,25 +1033,33 @@ void connectionInfo::handleAccessoryRequest() { Poly1305_GenKey((const unsigned char *)temp2, (uint8_t *)reply, resultLen, Type_Data_With_Length, verify); memcpy((unsigned char*)&reply[resultLen+2], verify, 16); - write(subSocket, reply, resultLen+18); + send(subSocket, reply, resultLen+18,0); pthread_mutex_unlock(&mutex); - delete [] reply; delete [] resultData; } } while (len > 0); pthread_mutex_destroy(&mutex); - delete [] decryptData; connected = false; } //Object Logic PHKNetworkIP::~PHKNetworkIP() { - DNSServiceRefDeallocate(netServiceV4); + closeAcceptConnection(); + DNSServiceRefDeallocate(netServiceV4); + + for (int i = 0; i < numberOfClient; i++) { + if ( connection[i].subSocket >= 0 ) + { + pthread_join(connection[i].thread,NULL); + } + } + + SRP_finalize_library(); } const char *copyLine(const char *rawData, char *destination) { @@ -1028,6 +1145,11 @@ PHKNetworkMessageData & PHKNetworkMessageData::operator=(const PHKNetworkMessage for (int i = 0; i < 10; i++) { if (data.records[i].length) { records[i] = data.records[i]; + + if(records[i].length) + { + delete [] records[i].data; + } records[i].data = new char[records[i].length]; bcopy(data.records[i].data, records[i].data, data.records[i].length); } @@ -1036,7 +1158,9 @@ PHKNetworkMessageData & PHKNetworkMessageData::operator=(const PHKNetworkMessage } PHKNetworkMessageData::PHKNetworkMessageData(const char *rawData, unsigned short len) { - unsigned short delta = 0; + this->count = 0; + + unsigned short delta = 0; while (delta < len) { int index = recordIndex(rawData[delta+0]); if (index < 0) { @@ -1153,3 +1277,12 @@ PHKNetworkMessageDataRecord &PHKNetworkMessageDataRecord::operator=(const PHKNet PHKNetworkMessageDataRecord::~PHKNetworkMessageDataRecord() { if (length) delete [] data; } + +//remove all controller pairing +void resetControllerAll() +{ + AccessorySetAutoLock autolock; + + AccessorySet::getInstance().Controllers.resetController(); + g_currentConfigurationNum = 1; +} diff --git a/PHKNetworkIP.h b/PHKNetworkIP.h old mode 100644 new mode 100755 index 9f45870..3aee13f --- a/PHKNetworkIP.h +++ b/PHKNetworkIP.h @@ -7,10 +7,19 @@ // // -#include -#include -#include -#include +#ifdef _WIN32 + #include + #include + #include + #include + #include +#else + #include + #include + #include +#endif + +#include // linux->avahi windows->bonjoursdk #include #include @@ -68,30 +77,48 @@ typedef enum void broadcastMessage(void *sender, char *resultData, size_t resultLen); class PHKNetworkIP { + void setupSocket(); void handlePairSeup(int subSocket, char *buffer) const; void handlePairVerify(int subSocket, char *buffer) const; + public: - PHKNetworkIP(); + PHKNetworkIP(const string& name + ,const string& pinCode + ,const string& identity + ,const string& controllerRecordsPath); void handleConnection() const; ~PHKNetworkIP(); + + void closeAcceptConnection(); }; class PHKNetworkMessageDataRecord { public: - unsigned char index = 0; - char *data = 0; - unsigned int length = 0; - bool activate = false; + unsigned char index; + char *data; + unsigned int length; + bool activate; + PHKNetworkMessageDataRecord() + : index(0) + , data(0) + , length(0) + , activate(false) + { + } ~PHKNetworkMessageDataRecord(); PHKNetworkMessageDataRecord &operator=(const PHKNetworkMessageDataRecord&); }; class PHKNetworkMessageData { PHKNetworkMessageDataRecord records[10]; - unsigned char count = 0; + unsigned char count; public: - PHKNetworkMessageData() {} + PHKNetworkMessageData() + { + this->count = 0; + } + PHKNetworkMessageData(const char *rawData, unsigned short len); PHKNetworkMessageData(const PHKNetworkMessageData &data); PHKNetworkMessageData &operator=(const PHKNetworkMessageData &); @@ -127,14 +154,14 @@ class connectionInfo { pthread_t thread; pthread_mutex_t mutex; - bool connected = false; + bool connected; uint8_t controllerToAccessoryKey[32]; uint8_t accessoryToControllerKey[32]; - unsigned long long numberOfMsgRec = 0; - unsigned long long numberOfMsgSend = 0; - int subSocket = -1; - char buffer[4096]; + unsigned long long numberOfMsgRec; + unsigned long long numberOfMsgSend; + int subSocket; + char buffer[4096+1]; void *notificationList[numberOfNotifiableValue]; @@ -142,6 +169,22 @@ class connectionInfo { void handlePairVerify(); void handleAccessoryRequest(); + connectionInfo() + { + init(); + } + void init() + { + subSocket = (-1); + numberOfMsgRec = (0); + numberOfMsgSend = (0); + connected = (false); + memset(buffer,0,4096+1); + memset(notificationList,0,sizeof(void*)*numberOfNotifiableValue); + memset(controllerToAccessoryKey,0,sizeof(uint8_t)*32); + memset(accessoryToControllerKey,0,sizeof(uint8_t)*32); + } + void Poly1305_GenKey(const unsigned char * key, uint8_t * buf, uint16_t len, Poly1305Type_t type, char* verify); void addNotify(void *target) { @@ -175,3 +218,6 @@ class connectionInfo { }; void updateConfiguration(); + +//remove all controller pairing +void resetControllerAll(); diff --git a/Personal-HomeKit-HAP.vcxproj b/Personal-HomeKit-HAP.vcxproj new file mode 100755 index 0000000..d7c60e0 --- /dev/null +++ b/Personal-HomeKit-HAP.vcxproj @@ -0,0 +1,140 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {89C81753-1AFE-4F3C-B0FB-159F9BC02693} + PersonalHomeKitHAP + + + + Application + true + MultiByte + + + Application + false + true + MultiByte + + + + + + + + + + + + + $(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include + $(SolutionDir)$(Configuration)\;$(LibraryPath) + + + + Level3 + Disabled + HomeKitLog=1;OPENSSL_ENGINE;_CRT_SECURE_NO_DEPRECATE;STDC_HEADERS;WIN32;_MBCS;%(PreprocessorDefinitions) + ..\openssl\include;windows_support_include;$(BONJOUR_SDK_HOME)/Include + 4996 + + + true + openssl.lib;$(BONJOUR_SDK_HOME)/Lib/$(PlatformName)/dnssd.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + MaxSpeed + true + true + + + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Personal-HomeKit-HAP.vcxproj.filters b/Personal-HomeKit-HAP.vcxproj.filters new file mode 100755 index 0000000..0b357d3 --- /dev/null +++ b/Personal-HomeKit-HAP.vcxproj.filters @@ -0,0 +1,201 @@ + + + + + {f6cf986d-69f1-47dc-b0c8-1e6ddbd14868} + + + {bd079260-fcdd-4ac0-a261-86033f0cedb8} + + + {7bddeea4-8d42-4bda-9889-d3a654eac7ce} + + + {bae2b6a2-57ef-4b8d-b5a6-197d87ab0f76} + + + {a842e132-cea7-4d9a-a055-6ff3ebacd4f7} + + + {5146eaa5-edee-463b-98b7-3b5e2a5ef71f} + + + + + Chacha20 + + + curve25519 + + + ed25519-donna + + + ed25519-donna + + + ed25519-donna + + + ed25519-donna + + + ed25519-donna + + + ed25519-donna + + + ed25519-donna + + + ed25519-donna + + + ed25519-donna + + + ed25519-donna + + + ed25519-donna + + + ed25519-donna + + + ed25519-donna + + + poly1305-opt-master + + + rfc6234-master + + + rfc6234-master + + + srp + + + srp + + + srp + + + srp + + + srp + + + srp + + + srp + + + srp + + + srp + + + srp + + + srp + + + srp + + + srp + + + srp + + + srp + + + srp + + + srp + + + srp + + + srp + + + srp + + + + + + + + + Chacha20 + + + curve25519 + + + ed25519-donna + + + poly1305-opt-master + + + rfc6234-master + + + rfc6234-master + + + rfc6234-master + + + srp + + + srp + + + srp + + + srp + + + srp + + + srp + + + srp + + + srp + + + srp + + + srp + + + + + + + + \ No newline at end of file diff --git a/Personal-HomeKit-HAP.vcxproj.user b/Personal-HomeKit-HAP.vcxproj.user new file mode 100755 index 0000000..695b5c7 --- /dev/null +++ b/Personal-HomeKit-HAP.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/ed25519-donna/ed25519.c b/ed25519-donna/ed25519.c index 58a755b..555e5e6 100755 --- a/ed25519-donna/ed25519.c +++ b/ed25519-donna/ed25519.c @@ -16,7 +16,6 @@ #include "ed25519-donna.h" #include "ed25519.h" -#include "ed25519-randombytes.h" #include "ed25519-hash.h" /* @@ -148,3 +147,5 @@ ED25519_FN(curved25519_scalarmult_basepoint) (curved25519_key pk, const curved25 curve25519_contract(pk, yplusz); } +//This does not work unless it is at the bottom because of the order of winsock used in windows openssl. +#include "ed25519-randombytes.h" diff --git a/main.cpp b/main.cpp old mode 100644 new mode 100755 index 867b49a..bbc0270 --- a/main.cpp +++ b/main.cpp @@ -61,19 +61,35 @@ int main(int argc, const char * argv[]) { printf("poweron: %d\n", poly1305_power_on_self_test()); #endif - // insert code here... - if (argc > 1) { - //If there's some argument - //Currently means reset - resetControllerRecord(); - } +#ifdef _WIN32 + WSADATA wsaData; + WSAStartup(2 , &wsaData); +#endif + // + PHKNetworkIP networkIP(deviceName,devicePassword,deviceIdentity,controllerRecordsAddress); + + // insert code here... + if (argc > 1) { + //If there's some argument + //Currently means reset + resetControllerAll(); + } initAccessorySet(); - setupPort(); +#ifdef _WIN32 +#else + setupPort(); +#endif - PHKNetworkIP networkIP; do { networkIP.handleConnection(); } while (true); - return 0; + + //if you running PHKNetworkIP new accept thread, + //call PHKNetworkIP::closeAcceptConnection to stop. + +#ifdef _WIN32 + WSACleanup(); +#endif + return 0; } diff --git a/makefile b/makefile index f2cf028..f5e8086 100644 --- a/makefile +++ b/makefile @@ -1,5 +1,5 @@ LINK = -lssl -lcrypto -ldl -lpthread -CFLAG = -Os -s +CFLAG = -Os -s -I/usr/local/ssl/include/ -I/usr/local/include/ -I/usr/local/include/avahi-compat-libdns_sd/ CC = gcc CPP = g++ PHK_LIBNAME=libphk diff --git a/srp/srp.h b/srp/srp.h index 4f89f5b..a8648e1 100755 --- a/srp/srp.h +++ b/srp/srp.h @@ -51,8 +51,8 @@ typedef int SRP_RESULT; /* Set the minimum number of bits acceptable in an SRP modulus */ #define SRP_DEFAULT_MIN_BITS 512 -_TYPE( SRP_RESULT ) SRP_set_modulus_min_bits P((int minbits)); -_TYPE( int ) SRP_get_modulus_min_bits P((void)); +_TYPE( SRP_RESULT ) SRP_set_modulus_min_bits (int minbits); +_TYPE( int ) SRP_get_modulus_min_bits (void); /* * Sets the "secret size callback" function. @@ -61,8 +61,8 @@ _TYPE( int ) SRP_get_modulus_min_bits P((void)); * The default function always returns 256 bits. */ typedef int (_CDECL * SRP_SECRET_BITS_CB)(int modsize); -_TYPE( SRP_RESULT ) SRP_set_secret_bits_cb P((SRP_SECRET_BITS_CB cb)); -_TYPE( int ) SRP_get_secret_bits P((int modsize)); +_TYPE( SRP_RESULT ) SRP_set_secret_bits_cb (SRP_SECRET_BITS_CB cb); +_TYPE( int ) SRP_get_secret_bits (int modsize); typedef struct srp_st SRP; @@ -97,15 +97,15 @@ struct srp_server_lu_st { * called to do lookups. */ _TYPE( SRP_SERVER_LOOKUP * ) - SRP_SERVER_LOOKUP_new P((SRP_SERVER_LOOKUP_METHOD * meth)); -_TYPE( SRP_RESULT ) SRP_SERVER_LOOKUP_free P((SRP_SERVER_LOOKUP * slu)); -_TYPE( SRP_RESULT ) SRP_SERVER_do_lookup P((SRP_SERVER_LOOKUP * slu, - SRP * srp, cstr * username)); + SRP_SERVER_LOOKUP_new (SRP_SERVER_LOOKUP_METHOD * meth); +_TYPE( SRP_RESULT ) SRP_SERVER_LOOKUP_free (SRP_SERVER_LOOKUP * slu); +_TYPE( SRP_RESULT ) SRP_SERVER_do_lookup (SRP_SERVER_LOOKUP * slu, + SRP * srp, cstr * username); /* * SRP_SERVER_system_lookup supercedes SRP_server_init_user. */ -_TYPE( SRP_SERVER_LOOKUP * ) SRP_SERVER_system_lookup P((void)); +_TYPE( SRP_SERVER_LOOKUP * ) SRP_SERVER_system_lookup (void); /* * Client Parameter Verification API @@ -213,8 +213,8 @@ _TYPE( SRP_RESULT ) SRP_finalize_library(); * the object operates in. SRP_free() frees it. * (See RFC2945 method definitions below.) */ -_TYPE( SRP * ) SRP_new P((SRP_METHOD * meth)); -_TYPE( SRP_RESULT ) SRP_free P((SRP * srp)); +_TYPE( SRP * ) SRP_new (SRP_METHOD * meth); +_TYPE( SRP_RESULT ) SRP_free (SRP * srp); /* * Use the supplied lookup object to look up user parameters and @@ -224,16 +224,16 @@ _TYPE( SRP_RESULT ) SRP_free P((SRP * srp)); * SRP_set_authenticator, since the lookup function handles that * internally. */ -_TYPE( SRP_RESULT ) SRP_set_server_lookup P((SRP * srp, - SRP_SERVER_LOOKUP * lookup)); +_TYPE( SRP_RESULT ) SRP_set_server_lookup (SRP * srp, + SRP_SERVER_LOOKUP * lookup); /* * Use the supplied callback function to verify parameters * (modulus, generator) given to the client. */ _TYPE( SRP_RESULT ) - SRP_set_client_param_verify_cb P((SRP * srp, - SRP_CLIENT_PARAM_VERIFY_CB cb)); + SRP_set_client_param_verify_cb (SRP * srp, + SRP_CLIENT_PARAM_VERIFY_CB cb); /* * Both client and server must call both SRP_set_username and @@ -241,14 +241,14 @@ _TYPE( SRP_RESULT ) * SRP_set_user_raw is an alternative to SRP_set_username that * accepts an arbitrary length-bounded octet string as input. */ -_TYPE( SRP_RESULT ) SRP_set_username P((SRP * srp, const char * username)); -_TYPE( SRP_RESULT ) SRP_set_user_raw P((SRP * srp, const unsigned char * user, - int userlen)); +_TYPE( SRP_RESULT ) SRP_set_username (SRP * srp, const char * username); +_TYPE( SRP_RESULT ) SRP_set_user_raw (SRP * srp, const unsigned char * user, + int userlen); _TYPE( SRP_RESULT ) - SRP_set_params P((SRP * srp, + SRP_set_params (SRP * srp, const unsigned char * modulus, int modlen, const unsigned char * generator, int genlen, - const unsigned char * salt, int saltlen)); + const unsigned char * salt, int saltlen); /* * On the client, SRP_set_authenticator, SRP_gen_exp, and @@ -270,13 +270,13 @@ _TYPE( SRP_RESULT ) * SRP_set_authenticator (since it doesn't know the plaintext password). */ _TYPE( SRP_RESULT ) - SRP_set_authenticator P((SRP * srp, const unsigned char * a, int alen)); + SRP_set_authenticator (SRP * srp, const unsigned char * a, int alen); _TYPE( SRP_RESULT ) - SRP_set_auth_password P((SRP * srp, const char * password)); + SRP_set_auth_password (SRP * srp, const char * password); _TYPE( SRP_RESULT ) - SRP_set_auth_password_raw P((SRP * srp, + SRP_set_auth_password_raw (SRP * srp, const unsigned char * password, - int passlen)); + int passlen); /* * SRP_gen_pub generates the random exponential residue to send @@ -293,21 +293,21 @@ _TYPE( SRP_RESULT ) * although the big integer value will still be available * through srp->pubkey in the SRP struct. */ -_TYPE( SRP_RESULT ) SRP_gen_pub P((SRP * srp, cstr ** result)); +_TYPE( SRP_RESULT ) SRP_gen_pub (SRP * srp, cstr ** result); /* * Append the data to the extra data segment. Authentication will * not succeed unless both sides add precisely the same data in * the same order. */ -_TYPE( SRP_RESULT ) SRP_add_ex_data P((SRP * srp, const unsigned char * data, - int datalen)); +_TYPE( SRP_RESULT ) SRP_add_ex_data (SRP * srp, const unsigned char * data, + int datalen); /* * SRP_compute_key must be called after the previous three methods. */ -_TYPE( SRP_RESULT ) SRP_compute_key P((SRP * srp, cstr ** result, +_TYPE( SRP_RESULT ) SRP_compute_key (SRP * srp, cstr ** result, const unsigned char * pubkey, - int pubkeylen)); + int pubkeylen); /* * On the client, call SRP_respond first to get the response to send @@ -317,9 +317,9 @@ _TYPE( SRP_RESULT ) SRP_compute_key P((SRP * srp, cstr ** result, * * It is an error to call SRP_respond with a NULL pointer. */ -_TYPE( SRP_RESULT ) SRP_verify P((SRP * srp, - const unsigned char * proof, int prooflen)); -_TYPE( SRP_RESULT ) SRP_respond P((SRP * srp, cstr ** response)); +_TYPE( SRP_RESULT ) SRP_verify (SRP * srp, + const unsigned char * proof, int prooflen); +_TYPE( SRP_RESULT ) SRP_respond (SRP * srp, cstr ** response); /* RFC2945-style SRP authentication */ @@ -330,17 +330,17 @@ _TYPE( SRP_RESULT ) SRP_respond P((SRP * srp, cstr ** response)); * RFC2945-style SRP authentication methods. Use these like: * SRP * srp = SRP_new(SRP_RFC2945_client_method()); */ -_TYPE( SRP_METHOD * ) SRP_RFC2945_client_method P((void)); -_TYPE( SRP_METHOD * ) SRP_RFC2945_server_method P((void)); +_TYPE( SRP_METHOD * ) SRP_RFC2945_client_method (void); +_TYPE( SRP_METHOD * ) SRP_RFC2945_server_method (void); /* * SRP-6 and SRP-6a authentication methods. * SRP-6a is recommended for better resistance to 2-for-1 attacks. */ -_TYPE( SRP_METHOD * ) SRP6_client_method P((void)); -_TYPE( SRP_METHOD * ) SRP6_server_method P((void)); -_TYPE( SRP_METHOD * ) SRP6a_client_method P((void)); -_TYPE( SRP_METHOD * ) SRP6a_server_method P((void)); +_TYPE( SRP_METHOD * ) SRP6_client_method (void); +_TYPE( SRP_METHOD * ) SRP6_server_method (void); +_TYPE( SRP_METHOD * ) SRP6a_client_method (void); +_TYPE( SRP_METHOD * ) SRP6a_server_method (void); /* * Convenience function - SRP_server_init_user @@ -351,12 +351,12 @@ _TYPE( SRP_METHOD * ) SRP6a_server_method P((void)); * This is deprecated in favor of SRP_SERVER_system_lookup() and * the Server Lookup API. */ -_TYPE( SRP_RESULT ) SRP_server_init_user P((SRP * srp, const char * username)); +_TYPE( SRP_RESULT ) SRP_server_init_user (SRP * srp, const char * username); /* * Use the named engine for acceleration. */ -_TYPE( SRP_RESULT ) SRP_use_engine P((const char * engine)); +_TYPE( SRP_RESULT ) SRP_use_engine (const char * engine); #ifdef __cplusplus } diff --git a/srp/srp6_server.c b/srp/srp6_server.c index ea9ceef..dc95499 100755 --- a/srp/srp6_server.c +++ b/srp/srp6_server.c @@ -258,6 +258,7 @@ srp6_server_key(SRP * srp, cstr ** result, cstr * s; BigInteger t1, t2, t3; SHACTX ctxt; + SHACTX sctx; unsigned char dig[SHA_DIGESTSIZE]; int modlen; @@ -331,7 +332,6 @@ srp6_server_key(SRP * srp, cstr ** result, BigIntegerClearFree(t3); /* convert srp->key into session key, update hashes */ - SHACTX sctx; BigIntegerToCstr(srp->key, s); SHAInit(&sctx); SHAUpdate(&sctx, s->data, s->length); diff --git a/srp/t_defines.h b/srp/t_defines.h index fc5b5d5..e5032dd 100755 --- a/srp/t_defines.h +++ b/srp/t_defines.h @@ -90,6 +90,13 @@ char *strchr(), *strrchr(), *strtok(); #include +#ifdef WIN32 +#include +#include +#define USE_FTIME 1 +#define USE_RENAME 1 +#define NO_FCHMOD 1 +#else #if TIME_WITH_SYS_TIME #include #include @@ -121,12 +128,10 @@ char *strchr(), *strrchr(), *strtok(); #define TERMIO struct sgttyb #define USE_SGTTY #endif +#endif /* WIN32 */ + + -#ifdef WIN32 -#define USE_FTIME 1 -#define USE_RENAME 1 -#define NO_FCHMOD 1 -#endif #ifdef USE_FTIME #include diff --git a/srp/t_misc.c b/srp/t_misc.c index cbbe6ee..9d91416 100755 --- a/srp/t_misc.c +++ b/srp/t_misc.c @@ -37,11 +37,12 @@ #include #include #include -#include #ifdef WIN32 #include #include +#else +#include #endif #include "t_sha.h" @@ -78,7 +79,10 @@ SHACTX randctxt; * tricks with variable ordering and sometimes define quirky * environment variables like $WINDOWID or $_. */ +#ifdef _WIN32 +#else extern char ** environ; +#endif static void t_envhash(out) diff --git a/windows_support_include/pthread.h b/windows_support_include/pthread.h new file mode 100755 index 0000000..3bad688 --- /dev/null +++ b/windows_support_include/pthread.h @@ -0,0 +1,65 @@ +#pragma once +//simple pthread emulation by rti + +#include +#include + +typedef CRITICAL_SECTION pthread_mutex_t; + +static void pthread_mutex_init(pthread_mutex_t* mutex, void* nazo) +{ + InitializeCriticalSection(mutex); +} + +static void pthread_mutex_destroy(pthread_mutex_t* mutex) +{ + DeleteCriticalSection(mutex); +} + +static void pthread_mutex_lock(pthread_mutex_t* mutex) +{ + EnterCriticalSection(mutex); +} + +static void pthread_mutex_unlock(pthread_mutex_t* mutex) +{ + LeaveCriticalSection(mutex); +} + +struct _threadcallback{ + static unsigned int __stdcall call(void* arg){ + _threadcallback* _this = ((_threadcallback*)arg); + _this->start_routine(_this->arg); + + delete _this; + return 0; + } + + void *(*start_routine) (void *); + void *arg; +}; + +typedef HANDLE pthread_t; +typedef void* pthread_attr_t; +static int pthread_create(pthread_t* thread, const pthread_attr_t *attr_null,void *(*start_routine) (void *), void *arg) +{ + _threadcallback* c = new _threadcallback; + c->start_routine = start_routine; + c->arg = arg; + + *thread = (HANDLE)_beginthreadex(NULL , 0 , _threadcallback::call , (void*)c , 0 ,NULL ); + return 1; +} + +static int pthread_join(pthread_t thread,void * nazo) +{ + ::WaitForSingleObject( thread , INFINITE); + ::CloseHandle(thread); + return 1; +} + +static int pthread_detach(pthread_t thread) +{ + ::CloseHandle(thread); + return 1; +} diff --git a/windows_support_include/strings.h b/windows_support_include/strings.h new file mode 100755 index 0000000..dbab1ab --- /dev/null +++ b/windows_support_include/strings.h @@ -0,0 +1,10 @@ +#pragma once + +#define bzero(b,len) (memset((b), '\0', (len)), (void) 0) +#define bcopy(b1,b2,len) (memmove((b2), (b1), (len)), (void) 0) +#define bcmp(b1,b2,len) (memcmp(b1,b2,len)) +#define strtok_r strtok_s + +#define __func__ __FUNCTION__ + + diff --git a/windows_support_include/unistd.h b/windows_support_include/unistd.h new file mode 100755 index 0000000..40259b3 --- /dev/null +++ b/windows_support_include/unistd.h @@ -0,0 +1,115 @@ +// in windows +//orignal soruce code: http://d.hatena.ne.jp/deraw/20070517/1179334643 +#ifndef _UNISTD_H_ +#define _UNISTD_H_ +#ifdef _WIN32 +#pragma once + +#include +/* +access +chmod +chsize +close +creat +dup +dup2 +eof +filelength +isatty +locking +lseek +mktemp +open +read +setmode +sopen +tell +umask +unlink +write +*/ +#include +/* +chdir +getcwd +mkdir +rmdir +*/ +#include +/* +cwait +execl +execle +execlp +execlpe +execv +execve +execvp +execvpe +spawnl +spawnle +spawnlp +spawnlpe +spawnv +spawnve +spawnvp +spawnvpe + +*/ +#pragma comment( lib, "ws2_32" ) +#include +/* +gethostname +*/ + +#include +/* +_getpid +*/ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int pid_t; /* process id type */ + +#ifndef _SSIZE_T_DEFINED +typedef int ssize_t; +#define _SSIZE_T_DEFINED +#endif + +#ifndef vsnprintf +#define vsnprintf(s, n, format, ...) _vsnprintf_s(s, n, _TRUNCATE, format, __VA_ARGS__) +#endif + +#ifndef snprintf +#define snprintf(s, n, format, ...) _snprintf_s(s, n, _TRUNCATE, format, __VA_ARGS__) +#endif + + +#define nice(incr) (SetPriorityClass(GetCurrentProcess(),incr))//TODO +#define sleep(seconds) (Sleep(seconds*1000)) +#define usleep(useconds) (Sleep(useconds)) + +#define stime(tp) UNISTD_stime(tp) +__forceinline int UNISTD_stime(const time_t *tp ){ + FILETIME ft; + SYSTEMTIME st; + LONGLONG ll = Int32x32To64(*tp, 10000000) + 116444736000000000; + ft.dwLowDateTime = (DWORD) ll; + ft.dwHighDateTime = (DWORD)(ll >>32); + FileTimeToSystemTime(&ft,&st); + return SetSystemTime(&st); +} + +// +#define fstat64(fildes, stat) (_fstati64(fildes, stat)) +#define stat64(path, buffer) (_stati64(path,buffer)) + +#ifdef __cplusplus +} +#endif +#endif /* _WIN32 */ +#endif /* _UNISTD_H_ */