00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifndef _WIN32
00011 #ifndef _BSD_SOURCE
00012 #define _BSD_SOURCE // for usleep from unistd.h
00013 #endif
00014 #ifndef _GNU_SOURCE
00015 #define _GNU_SOURCE
00016 #endif
00017 #endif
00018
00019 #include <errno.h>
00020 #include <stddef.h>
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include <time.h>
00025
00026 #ifdef _WIN32
00027 #include <winsock2.h>
00028 #include <wincrypt.h>
00029 #include <process.h>
00030 #else
00031 #include <fcntl.h>
00032 #include <unistd.h>
00033 #include <sys/types.h>
00034 #include <sys/socket.h>
00035 #include <sys/select.h>
00036 #include <sys/stat.h>
00037 #include <netinet/tcp.h>
00038 #include <netdb.h>
00039 #include <netinet/in.h>
00040 #endif
00041
00042 #ifdef _MSC_VER
00043
00044 #define getpid GetCurrentProcessId
00045 #else
00046 #include <sys/time.h>
00047 #endif
00048
00049 #define IPCON_EXPOSE_INTERNALS
00050
00051 #include "ip_connection.h"
00052
00053 #ifdef __cplusplus
00054 extern "C" {
00055 #endif
00056
00057 #if defined _MSC_VER || defined __BORLANDC__
00058 #pragma pack(push)
00059 #pragma pack(1)
00060 #define ATTRIBUTE_PACKED
00061 #elif defined __GNUC__
00062 #ifdef _WIN32
00063
00064
00065 #define ATTRIBUTE_PACKED __attribute__((gcc_struct, packed))
00066 #else
00067 #define ATTRIBUTE_PACKED __attribute__((packed))
00068 #endif
00069 #else
00070 #error unknown compiler, do not know how to enable struct packing
00071 #endif
00072
00073 typedef struct {
00074 PacketHeader header;
00075 } ATTRIBUTE_PACKED Enumerate;
00076
00077 typedef struct {
00078 PacketHeader header;
00079 char uid[8];
00080 char connected_uid[8];
00081 char position;
00082 uint8_t hardware_version[3];
00083 uint8_t firmware_version[3];
00084 uint16_t device_identifier;
00085 uint8_t enumeration_type;
00086 } ATTRIBUTE_PACKED EnumerateCallback;
00087
00088 typedef struct {
00089 PacketHeader header;
00090 } ATTRIBUTE_PACKED GetAuthenticationNonce;
00091
00092 typedef struct {
00093 PacketHeader header;
00094 uint8_t server_nonce[4];
00095 } ATTRIBUTE_PACKED GetAuthenticationNonceResponse;
00096
00097 typedef struct {
00098 PacketHeader header;
00099 uint8_t client_nonce[4];
00100 uint8_t digest[20];
00101 } ATTRIBUTE_PACKED Authenticate;
00102
00103 #if defined _MSC_VER || defined __BORLANDC__
00104 #pragma pack(pop)
00105 #endif
00106 #undef ATTRIBUTE_PACKED
00107
00108 #ifndef __cplusplus
00109 #ifdef __GNUC__
00110 #ifndef __GNUC_PREREQ
00111 #define __GNUC_PREREQ(major, minor) \
00112 ((((__GNUC__) << 16) + (__GNUC_MINOR__)) >= (((major) << 16) + (minor)))
00113 #endif
00114 #if __GNUC_PREREQ(4, 6)
00115 #define STATIC_ASSERT(condition, message) \
00116 _Static_assert(condition, message)
00117 #else
00118 #define STATIC_ASSERT(condition, message) // FIXME
00119 #endif
00120 #else
00121 #define STATIC_ASSERT(condition, message) // FIXME
00122 #endif
00123
00124 STATIC_ASSERT(sizeof(PacketHeader) == 8, "PacketHeader has invalid size");
00125 STATIC_ASSERT(sizeof(Packet) == 80, "Packet has invalid size");
00126 STATIC_ASSERT(sizeof(EnumerateCallback) == 34, "EnumerateCallback has invalid size");
00127 STATIC_ASSERT(sizeof(GetAuthenticationNonce) == 8, "GetAuthenticationNonce has invalid size");
00128 STATIC_ASSERT(sizeof(GetAuthenticationNonceResponse) == 12, "GetAuthenticationNonceResponse has invalid size");
00129 STATIC_ASSERT(sizeof(Authenticate) == 32, "Authenticate has invalid size");
00130 #endif
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151 #define SHA1_BLOCK_LENGTH 64
00152 #define SHA1_DIGEST_LENGTH 20
00153
00154 typedef struct {
00155 uint32_t state[5];
00156 uint64_t count;
00157 uint8_t buffer[SHA1_BLOCK_LENGTH];
00158 } SHA1;
00159
00160 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
00161
00162
00163 #define blk0(i) (block[i] = htonl(block[i]))
00164 #define blk(i) (block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15]^block[(i+2)&15]^block[i&15],1))
00165
00166
00167 #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
00168 #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
00169 #define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
00170 #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
00171 #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
00172
00173
00174 static uint32_t sha1_transform(SHA1 *sha1, const uint8_t buffer[SHA1_BLOCK_LENGTH]) {
00175 uint32_t a, b, c, d, e;
00176 uint32_t block[SHA1_BLOCK_LENGTH / 4];
00177
00178 memcpy(&block, buffer, SHA1_BLOCK_LENGTH);
00179
00180
00181 a = sha1->state[0];
00182 b = sha1->state[1];
00183 c = sha1->state[2];
00184 d = sha1->state[3];
00185 e = sha1->state[4];
00186
00187
00188 R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
00189 R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
00190 R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
00191 R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
00192 R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
00193
00194 R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
00195 R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
00196 R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
00197 R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
00198 R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
00199
00200 R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
00201 R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
00202 R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
00203 R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
00204 R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
00205
00206 R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
00207 R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
00208 R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
00209 R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
00210 R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
00211
00212
00213 sha1->state[0] += a;
00214 sha1->state[1] += b;
00215 sha1->state[2] += c;
00216 sha1->state[3] += d;
00217 sha1->state[4] += e;
00218
00219
00220 a = b = c = d = e = 0;
00221
00222 return a;
00223 }
00224
00225 static void sha1_init(SHA1 *sha1) {
00226 sha1->state[0] = 0x67452301;
00227 sha1->state[1] = 0xEFCDAB89;
00228 sha1->state[2] = 0x98BADCFE;
00229 sha1->state[3] = 0x10325476;
00230 sha1->state[4] = 0xC3D2E1F0;
00231 sha1->count = 0;
00232 }
00233
00234 static void sha1_update(SHA1 *sha1, const uint8_t *data, size_t length) {
00235 size_t i, j;
00236
00237 j = (size_t)((sha1->count >> 3) & 63);
00238 sha1->count += (length << 3);
00239
00240 if ((j + length) > 63) {
00241 i = 64 - j;
00242
00243 memcpy(&sha1->buffer[j], data, i);
00244 sha1_transform(sha1, sha1->buffer);
00245
00246 for (; i + 63 < length; i += 64) {
00247 sha1_transform(sha1, &data[i]);
00248 }
00249
00250 j = 0;
00251 } else {
00252 i = 0;
00253 }
00254
00255 memcpy(&sha1->buffer[j], &data[i], length - i);
00256 }
00257
00258 static void sha1_final(SHA1 *sha1, uint8_t digest[SHA1_DIGEST_LENGTH]) {
00259 uint32_t i;
00260 uint8_t count[8];
00261
00262 for (i = 0; i < 8; i++) {
00263
00264 count[i] = (uint8_t)((sha1->count >> ((7 - (i & 7)) * 8)) & 255);
00265 }
00266
00267 sha1_update(sha1, (uint8_t *)"\200", 1);
00268
00269 while ((sha1->count & 504) != 448) {
00270 sha1_update(sha1, (uint8_t *)"\0", 1);
00271 }
00272
00273 sha1_update(sha1, count, 8);
00274
00275 for (i = 0; i < SHA1_DIGEST_LENGTH; i++) {
00276 digest[i] = (uint8_t)((sha1->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255);
00277 }
00278
00279 memset(sha1, 0, sizeof(*sha1));
00280 }
00281
00282 #undef rol
00283 #undef blk0
00284 #undef blk
00285 #undef R0
00286 #undef R1
00287 #undef R2
00288 #undef R3
00289 #undef R4
00290
00291
00292
00293
00294
00295
00296
00297 static size_t string_length(const char *s, size_t max_length) {
00298 const char *p = s;
00299 size_t n = 0;
00300
00301 while (*p != '\0' && n < max_length) {
00302 ++p;
00303 ++n;
00304 }
00305
00306 return n;
00307 }
00308
00309 #ifdef _MSC_VER
00310
00311
00312 #define DELTA_EPOCH 116444736000000000ULL
00313
00314 typedef void (WINAPI *GETSYSTEMTIMEPRECISEASFILETIME)(LPFILETIME);
00315
00316
00317 static int gettimeofday(struct timeval *tv, struct timezone *tz) {
00318 GETSYSTEMTIMEPRECISEASFILETIME ptr_GetSystemTimePreciseAsFileTime = NULL;
00319 FILETIME ft;
00320 uint64_t t;
00321
00322 (void)tz;
00323
00324 if (tv != NULL) {
00325 ptr_GetSystemTimePreciseAsFileTime =
00326 (GETSYSTEMTIMEPRECISEASFILETIME)GetProcAddress(GetModuleHandleA("kernel32"),
00327 "GetSystemTimePreciseAsFileTime");
00328
00329 if (ptr_GetSystemTimePreciseAsFileTime != NULL) {
00330 ptr_GetSystemTimePreciseAsFileTime(&ft);
00331 } else {
00332 GetSystemTimeAsFileTime(&ft);
00333 }
00334
00335 t = ((uint64_t)ft.dwHighDateTime << 32) | (uint64_t)ft.dwLowDateTime;
00336 t = (t - DELTA_EPOCH) / 10;
00337
00338 tv->tv_sec = (long)(t / 1000000UL);
00339 tv->tv_usec = (long)(t % 1000000UL);
00340 }
00341
00342 return 0;
00343 }
00344
00345 #endif
00346
00347 #ifndef _WIN32
00348
00349 static int read_uint32_non_blocking(const char *filename, uint32_t *value) {
00350 int fd = open(filename, O_NONBLOCK);
00351 int rc;
00352
00353 if (fd < 0) {
00354 return -1;
00355 }
00356
00357 rc = read(fd, value, sizeof(uint32_t));
00358
00359 close(fd);
00360
00361 return rc != sizeof(uint32_t) ? -1 : 0;
00362 }
00363
00364 #endif
00365
00366
00367
00368 uint32_t get_random_uint32(void) {
00369 uint32_t r;
00370 struct timeval tv;
00371 uint32_t seconds;
00372 uint32_t microseconds;
00373 #ifdef _WIN32
00374 HCRYPTPROV hprovider;
00375
00376 if (!CryptAcquireContext(&hprovider, NULL, NULL, PROV_RSA_FULL,
00377 CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
00378 goto fallback;
00379 }
00380
00381 if (!CryptGenRandom(hprovider, sizeof(r), (BYTE *)&r)) {
00382 CryptReleaseContext(hprovider, 0);
00383
00384 goto fallback;
00385 }
00386
00387 CryptReleaseContext(hprovider, 0);
00388 #else
00389
00390
00391 if (read_uint32_non_blocking("/dev/urandom", &r) < 0) {
00392 if (read_uint32_non_blocking("/dev/random", &r) < 0) {
00393 goto fallback;
00394 }
00395 }
00396 #endif
00397
00398 return r;
00399
00400 fallback:
00401
00402 if (gettimeofday(&tv, NULL) < 0) {
00403 seconds = (uint32_t)time(NULL);
00404 microseconds = 0;
00405 } else {
00406 seconds = tv.tv_sec;
00407 microseconds = tv.tv_usec;
00408 }
00409
00410 return (seconds << 26 | seconds >> 6) + microseconds + getpid();
00411 }
00412
00413 static void hmac_sha1(uint8_t *secret, int secret_length,
00414 uint8_t *data, int data_length,
00415 uint8_t digest[SHA1_DIGEST_LENGTH]) {
00416 SHA1 sha1;
00417 uint8_t secret_digest[SHA1_DIGEST_LENGTH];
00418 uint8_t inner_digest[SHA1_DIGEST_LENGTH];
00419 uint8_t ipad[SHA1_BLOCK_LENGTH];
00420 uint8_t opad[SHA1_BLOCK_LENGTH];
00421 int i;
00422
00423 if (secret_length > SHA1_BLOCK_LENGTH) {
00424 sha1_init(&sha1);
00425 sha1_update(&sha1, secret, secret_length);
00426 sha1_final(&sha1, secret_digest);
00427
00428 secret = secret_digest;
00429 secret_length = SHA1_DIGEST_LENGTH;
00430 }
00431
00432
00433 for (i = 0; i < secret_length; ++i) {
00434 ipad[i] = secret[i] ^ 0x36;
00435 }
00436
00437 for (i = secret_length; i < SHA1_BLOCK_LENGTH; ++i) {
00438 ipad[i] = 0x36;
00439 }
00440
00441 sha1_init(&sha1);
00442 sha1_update(&sha1, ipad, SHA1_BLOCK_LENGTH);
00443 sha1_update(&sha1, data, data_length);
00444 sha1_final(&sha1, inner_digest);
00445
00446
00447 for (i = 0; i < secret_length; ++i) {
00448 opad[i] = secret[i] ^ 0x5C;
00449 }
00450
00451 for (i = secret_length; i < SHA1_BLOCK_LENGTH; ++i) {
00452 opad[i] = 0x5C;
00453 }
00454
00455 sha1_init(&sha1);
00456 sha1_update(&sha1, opad, SHA1_BLOCK_LENGTH);
00457 sha1_update(&sha1, inner_digest, SHA1_DIGEST_LENGTH);
00458 sha1_final(&sha1, digest);
00459 }
00460
00461
00462
00463
00464
00465
00466
00467 #define BASE58_MAX_STR_SIZE 13
00468
00469 static const char BASE58_ALPHABET[] = \
00470 "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";
00471
00472 #if 0
00473 static void base58_encode(uint64_t value, char *str) {
00474 uint32_t mod;
00475 char reverse_str[BASE58_MAX_STR_SIZE] = {'\0'};
00476 int i = 0;
00477 int k = 0;
00478
00479 while (value >= 58) {
00480 mod = value % 58;
00481 reverse_str[i] = BASE58_ALPHABET[mod];
00482 value = value / 58;
00483 ++i;
00484 }
00485
00486 reverse_str[i] = BASE58_ALPHABET[value];
00487
00488 for (k = 0; k <= i; k++) {
00489 str[k] = reverse_str[i - k];
00490 }
00491
00492 for (; k < BASE58_MAX_STR_SIZE; k++) {
00493 str[k] = '\0';
00494 }
00495 }
00496 #endif
00497
00498 static uint64_t base58_decode(const char *str) {
00499 int i;
00500 int k;
00501 uint64_t value = 0;
00502 uint64_t base = 1;
00503
00504 for (i = 0; i < BASE58_MAX_STR_SIZE; i++) {
00505 if (str[i] == '\0') {
00506 break;
00507 }
00508 }
00509
00510 --i;
00511
00512 for (; i >= 0; i--) {
00513 if (str[i] == '\0') {
00514 continue;
00515 }
00516
00517 for (k = 0; k < 58; k++) {
00518 if (BASE58_ALPHABET[k] == str[i]) {
00519 break;
00520 }
00521 }
00522
00523 value += k * base;
00524 base *= 58;
00525 }
00526
00527 return value;
00528 }
00529
00530
00531
00532
00533
00534
00535
00536 struct _Socket {
00537 #ifdef _WIN32
00538 SOCKET handle;
00539 #else
00540 int handle;
00541 #endif
00542 Mutex send_mutex;
00543 };
00544
00545 #ifdef _WIN32
00546
00547 static int socket_create(Socket *socket_, int domain, int type, int protocol) {
00548 BOOL flag = 1;
00549
00550 socket_->handle = socket(domain, type, protocol);
00551
00552 if (socket_->handle == INVALID_SOCKET) {
00553 return -1;
00554 }
00555
00556 if (setsockopt(socket_->handle, IPPROTO_TCP, TCP_NODELAY,
00557 (const char *)&flag, sizeof(flag)) == SOCKET_ERROR) {
00558 closesocket(socket_->handle);
00559
00560 return -1;
00561 }
00562
00563 mutex_create(&socket_->send_mutex);
00564
00565 return 0;
00566 }
00567
00568 static void socket_destroy(Socket *socket) {
00569 mutex_destroy(&socket->send_mutex);
00570
00571 closesocket(socket->handle);
00572 }
00573
00574 static int socket_connect(Socket *socket, struct sockaddr_in *address, int length) {
00575 return connect(socket->handle, (struct sockaddr *)address, length) == SOCKET_ERROR ? -1 : 0;
00576 }
00577
00578 static void socket_shutdown(Socket *socket) {
00579 shutdown(socket->handle, SD_BOTH);
00580 }
00581
00582 static int socket_receive(Socket *socket, void *buffer, int length) {
00583 length = recv(socket->handle, (char *)buffer, length, 0);
00584
00585 if (length == SOCKET_ERROR) {
00586 length = -1;
00587
00588 if (WSAGetLastError() == WSAEINTR) {
00589 errno = EINTR;
00590 } else {
00591 errno = EFAULT;
00592 }
00593 }
00594
00595 return length;
00596 }
00597
00598 static int socket_send(Socket *socket, void *buffer, int length) {
00599 mutex_lock(&socket->send_mutex);
00600
00601 length = send(socket->handle, (const char *)buffer, length, 0);
00602
00603 mutex_unlock(&socket->send_mutex);
00604
00605 if (length == SOCKET_ERROR) {
00606 length = -1;
00607 }
00608
00609 return length;
00610 }
00611
00612 #else
00613
00614 static int socket_create(Socket *socket_, int domain, int type, int protocol) {
00615 int flag = 1;
00616
00617 socket_->handle = socket(domain, type, protocol);
00618
00619 if (socket_->handle < 0) {
00620 return -1;
00621 }
00622
00623 if (setsockopt(socket_->handle, IPPROTO_TCP, TCP_NODELAY, (void *)&flag,
00624 sizeof(flag)) < 0) {
00625 close(socket_->handle);
00626
00627 return -1;
00628 }
00629
00630 mutex_create(&socket_->send_mutex);
00631
00632 return 0;
00633 }
00634
00635 static void socket_destroy(Socket *socket) {
00636 mutex_destroy(&socket->send_mutex);
00637
00638 close(socket->handle);
00639 }
00640
00641 static int socket_connect(Socket *socket, struct sockaddr_in *address, int length) {
00642 return connect(socket->handle, (struct sockaddr *)address, length);
00643 }
00644
00645 static void socket_shutdown(Socket *socket) {
00646 shutdown(socket->handle, SHUT_RDWR);
00647 }
00648
00649 static int socket_receive(Socket *socket, void *buffer, int length) {
00650 return recv(socket->handle, buffer, length, 0);
00651 }
00652
00653 static int socket_send(Socket *socket, void *buffer, int length) {
00654 int rc;
00655
00656 mutex_lock(&socket->send_mutex);
00657
00658 rc = send(socket->handle, buffer, length, 0);
00659
00660 mutex_unlock(&socket->send_mutex);
00661
00662 return rc;
00663 }
00664
00665 #endif
00666
00667
00668
00669
00670
00671
00672
00673 #ifdef _WIN32
00674
00675 void mutex_create(Mutex *mutex) {
00676 InitializeCriticalSection(&mutex->handle);
00677 }
00678
00679 void mutex_destroy(Mutex *mutex) {
00680 DeleteCriticalSection(&mutex->handle);
00681 }
00682
00683 void mutex_lock(Mutex *mutex) {
00684 EnterCriticalSection(&mutex->handle);
00685 }
00686
00687 void mutex_unlock(Mutex *mutex) {
00688 LeaveCriticalSection(&mutex->handle);
00689 }
00690
00691 #else
00692
00693 void mutex_create(Mutex *mutex) {
00694 pthread_mutex_init(&mutex->handle, NULL);
00695 }
00696
00697 void mutex_destroy(Mutex *mutex) {
00698 pthread_mutex_destroy(&mutex->handle);
00699 }
00700
00701 void mutex_lock(Mutex *mutex) {
00702 pthread_mutex_lock(&mutex->handle);
00703 }
00704
00705 void mutex_unlock(Mutex *mutex) {
00706 pthread_mutex_unlock(&mutex->handle);
00707 }
00708 #endif
00709
00710
00711
00712
00713
00714
00715
00716 #ifdef _WIN32
00717
00718 static void event_create(Event *event) {
00719 event->handle = CreateEvent(NULL, TRUE, FALSE, NULL);
00720 }
00721
00722 static void event_destroy(Event *event) {
00723 CloseHandle(event->handle);
00724 }
00725
00726 static void event_set(Event *event) {
00727 SetEvent(event->handle);
00728 }
00729
00730 static void event_reset(Event *event) {
00731 ResetEvent(event->handle);
00732 }
00733
00734 static int event_wait(Event *event, uint32_t timeout) {
00735 return WaitForSingleObject(event->handle, timeout) == WAIT_OBJECT_0 ? 0 : -1;
00736 }
00737
00738 #else
00739
00740 static void event_create(Event *event) {
00741 pthread_mutex_init(&event->mutex, NULL);
00742 pthread_cond_init(&event->condition, NULL);
00743
00744 event->flag = false;
00745 }
00746
00747 static void event_destroy(Event *event) {
00748 pthread_mutex_destroy(&event->mutex);
00749 pthread_cond_destroy(&event->condition);
00750 }
00751
00752 static void event_set(Event *event) {
00753 pthread_mutex_lock(&event->mutex);
00754
00755 event->flag = true;
00756
00757 pthread_cond_broadcast(&event->condition);
00758 pthread_mutex_unlock(&event->mutex);
00759 }
00760
00761 static void event_reset(Event *event) {
00762 pthread_mutex_lock(&event->mutex);
00763
00764 event->flag = false;
00765
00766 pthread_mutex_unlock(&event->mutex);
00767 }
00768
00769 static int event_wait(Event *event, uint32_t timeout) {
00770 struct timeval tp;
00771 struct timespec ts;
00772 int ret = E_OK;
00773
00774 gettimeofday(&tp, NULL);
00775
00776 ts.tv_sec = tp.tv_sec + timeout / 1000;
00777 ts.tv_nsec = (tp.tv_usec + (timeout % 1000) * 1000) * 1000;
00778
00779 while (ts.tv_nsec >= 1000000000L) {
00780 ts.tv_sec += 1;
00781 ts.tv_nsec -= 1000000000L;
00782 }
00783
00784 pthread_mutex_lock(&event->mutex);
00785
00786 while (!event->flag) {
00787 ret = pthread_cond_timedwait(&event->condition, &event->mutex, &ts);
00788
00789 if (ret != 0) {
00790 ret = E_TIMEOUT;
00791 break;
00792 }
00793 }
00794
00795 pthread_mutex_unlock(&event->mutex);
00796
00797 return ret;
00798 }
00799
00800 #endif
00801
00802
00803
00804
00805
00806
00807
00808 #ifdef _WIN32
00809
00810 static void semaphore_create(Semaphore *semaphore) {
00811 semaphore->handle = CreateSemaphore(NULL, 0, INT32_MAX, NULL);
00812 }
00813
00814 static void semaphore_destroy(Semaphore *semaphore) {
00815 CloseHandle(semaphore->handle);
00816 }
00817
00818 static int semaphore_acquire(Semaphore *semaphore) {
00819 return WaitForSingleObject(semaphore->handle, INFINITE) != WAIT_OBJECT_0 ? -1 : 0;
00820 }
00821
00822 static void semaphore_release(Semaphore *semaphore) {
00823 ReleaseSemaphore(semaphore->handle, 1, NULL);
00824 }
00825
00826 #else
00827
00828 static void semaphore_create(Semaphore *semaphore) {
00829 #ifdef __APPLE__
00830
00831
00832
00833
00834 char name[100];
00835
00836 snprintf(name, sizeof(name), "tf-ipcon-%p", semaphore);
00837
00838 sem_unlink(name);
00839 semaphore->pointer = sem_open(name, O_CREAT | O_EXCL, S_IRWXU, 0);
00840 sem_unlink(name);
00841 #else
00842 semaphore->pointer = &semaphore->object;
00843
00844 sem_init(semaphore->pointer, 0, 0);
00845 #endif
00846 }
00847
00848 static void semaphore_destroy(Semaphore *semaphore) {
00849 #ifdef __APPLE__
00850 sem_close(semaphore->pointer);
00851 #else
00852 sem_destroy(semaphore->pointer);
00853 #endif
00854 }
00855
00856 static int semaphore_acquire(Semaphore *semaphore) {
00857 return sem_wait(semaphore->pointer) < 0 ? -1 : 0;
00858 }
00859
00860 static void semaphore_release(Semaphore *semaphore) {
00861 sem_post(semaphore->pointer);
00862 }
00863
00864 #endif
00865
00866
00867
00868
00869
00870
00871
00872 #ifdef _WIN32
00873
00874 static DWORD WINAPI thread_wrapper(void *opaque) {
00875 Thread *thread = (Thread *)opaque;
00876
00877 thread->function(thread->opaque);
00878
00879 return 0;
00880 }
00881
00882 static int thread_create(Thread *thread, ThreadFunction function, void *opaque) {
00883 thread->function = function;
00884 thread->opaque = opaque;
00885
00886 thread->handle = CreateThread(NULL, 0, thread_wrapper, thread, 0, &thread->id);
00887
00888 return thread->handle == NULL ? -1 : 0;
00889 }
00890
00891 static void thread_destroy(Thread *thread) {
00892 CloseHandle(thread->handle);
00893 }
00894
00895 static bool thread_is_current(Thread *thread) {
00896 return thread->id == GetCurrentThreadId();
00897 }
00898
00899 static void thread_join(Thread *thread) {
00900 WaitForSingleObject(thread->handle, INFINITE);
00901 }
00902
00903 static void thread_sleep(int msec) {
00904 Sleep(msec);
00905 }
00906
00907 #else
00908
00909 static void *thread_wrapper(void *opaque) {
00910 Thread *thread = (Thread *)opaque;
00911
00912 thread->function(thread->opaque);
00913
00914 return NULL;
00915 }
00916
00917 static int thread_create(Thread *thread, ThreadFunction function, void *opaque) {
00918 thread->function = function;
00919 thread->opaque = opaque;
00920
00921 return pthread_create(&thread->handle, NULL, thread_wrapper, thread);
00922 }
00923
00924 static void thread_destroy(Thread *thread) {
00925 (void)thread;
00926 }
00927
00928 static bool thread_is_current(Thread *thread) {
00929 return pthread_equal(thread->handle, pthread_self()) ? true : false;
00930 }
00931
00932 static void thread_join(Thread *thread) {
00933 pthread_join(thread->handle, NULL);
00934 }
00935
00936 static void thread_sleep(int msec) {
00937 usleep(msec * 1000);
00938 }
00939
00940 #endif
00941
00942
00943
00944
00945
00946
00947
00948 static void table_create(Table *table) {
00949 mutex_create(&table->mutex);
00950
00951 table->used = 0;
00952 table->allocated = 16;
00953 table->keys = (uint32_t *)malloc(sizeof(uint32_t) * table->allocated);
00954 table->values = (void **)malloc(sizeof(void *) * table->allocated);
00955 }
00956
00957 static void table_destroy(Table *table) {
00958 free(table->keys);
00959 free(table->values);
00960
00961 mutex_destroy(&table->mutex);
00962 }
00963
00964 static void table_insert(Table *table, uint32_t key, void *value) {
00965 int i;
00966
00967 mutex_lock(&table->mutex);
00968
00969 for (i = 0; i < table->used; ++i) {
00970 if (table->keys[i] == key) {
00971 table->values[i] = value;
00972
00973 mutex_unlock(&table->mutex);
00974
00975 return;
00976 }
00977 }
00978
00979 if (table->allocated <= table->used) {
00980 table->allocated += 16;
00981 table->keys = (uint32_t *)realloc(table->keys, sizeof(uint32_t) * table->allocated);
00982 table->values = (void **)realloc(table->values, sizeof(void *) * table->allocated);
00983 }
00984
00985 table->keys[table->used] = key;
00986 table->values[table->used] = value;
00987
00988 ++table->used;
00989
00990 mutex_unlock(&table->mutex);
00991 }
00992
00993 static void table_remove(Table *table, uint32_t key) {
00994 int i;
00995 int tail;
00996
00997 mutex_lock(&table->mutex);
00998
00999 for (i = 0; i < table->used; ++i) {
01000 if (table->keys[i] == key) {
01001 tail = table->used - i - 1;
01002
01003 if (tail > 0) {
01004 memmove(table->keys + i, table->keys + i + 1, sizeof(uint32_t) * tail);
01005 memmove(table->values + i, table->values + i + 1, sizeof(void *) * tail);
01006 }
01007
01008 --table->used;
01009
01010 break;
01011 }
01012 }
01013
01014 mutex_unlock(&table->mutex);
01015 }
01016
01017 static void *table_get(Table *table, uint32_t key) {
01018 int i;
01019 void *value = NULL;
01020
01021 mutex_lock(&table->mutex);
01022
01023 for (i = 0; i < table->used; ++i) {
01024 if (table->keys[i] == key) {
01025 value = table->values[i];
01026
01027 break;
01028 }
01029 }
01030
01031 mutex_unlock(&table->mutex);
01032
01033 return value;
01034 }
01035
01036
01037
01038
01039
01040
01041
01042 enum {
01043 QUEUE_KIND_EXIT = 0,
01044 QUEUE_KIND_META,
01045 QUEUE_KIND_PACKET
01046 };
01047
01048 typedef struct {
01049 uint8_t function_id;
01050 uint8_t parameter;
01051 uint64_t socket_id;
01052 } Meta;
01053
01054 static void queue_create(Queue *queue) {
01055 queue->head = NULL;
01056 queue->tail = NULL;
01057
01058 mutex_create(&queue->mutex);
01059 semaphore_create(&queue->semaphore);
01060 }
01061
01062 static void queue_destroy(Queue *queue) {
01063 QueueItem *item = queue->head;
01064 QueueItem *next;
01065
01066 while (item != NULL) {
01067 next = item->next;
01068
01069 free(item->data);
01070 free(item);
01071
01072 item = next;
01073 }
01074
01075 mutex_destroy(&queue->mutex);
01076 semaphore_destroy(&queue->semaphore);
01077 }
01078
01079 static void queue_put(Queue *queue, int kind, void *data) {
01080 QueueItem *item = (QueueItem *)malloc(sizeof(QueueItem));
01081
01082 item->next = NULL;
01083 item->kind = kind;
01084 item->data = data;
01085
01086 mutex_lock(&queue->mutex);
01087
01088 if (queue->tail == NULL) {
01089 queue->head = item;
01090 queue->tail = item;
01091 } else {
01092 queue->tail->next = item;
01093 queue->tail = item;
01094 }
01095
01096 mutex_unlock(&queue->mutex);
01097 semaphore_release(&queue->semaphore);
01098 }
01099
01100 static int queue_get(Queue *queue, int *kind, void **data) {
01101 QueueItem *item;
01102
01103 if (semaphore_acquire(&queue->semaphore) < 0) {
01104 return -1;
01105 }
01106
01107 mutex_lock(&queue->mutex);
01108
01109 if (queue->head == NULL) {
01110 mutex_unlock(&queue->mutex);
01111
01112 return -1;
01113 }
01114
01115 item = queue->head;
01116 queue->head = item->next;
01117 item->next = NULL;
01118
01119 if (queue->tail == item) {
01120 queue->head = NULL;
01121 queue->tail = NULL;
01122 }
01123
01124 mutex_unlock(&queue->mutex);
01125
01126 *kind = item->kind;
01127 *data = item->data;
01128
01129 free(item);
01130
01131 return 0;
01132 }
01133
01134
01135
01136
01137
01138
01139
01140 enum {
01141 IPCON_FUNCTION_ENUMERATE = 254
01142 };
01143
01144 static int ipcon_send_request(IPConnectionPrivate *ipcon_p, Packet *request);
01145
01146
01147 static void device_destroy(DevicePrivate *device_p) {
01148 table_remove(&device_p->ipcon_p->devices, device_p->uid);
01149
01150 event_destroy(&device_p->response_event);
01151
01152 mutex_destroy(&device_p->response_mutex);
01153
01154 mutex_destroy(&device_p->request_mutex);
01155
01156 free(device_p);
01157 }
01158
01159 void device_create(Device *device, const char *uid_str,
01160 IPConnectionPrivate *ipcon_p, uint8_t api_version_major,
01161 uint8_t api_version_minor, uint8_t api_version_release) {
01162 DevicePrivate *device_p;
01163 uint64_t uid;
01164 uint32_t value1;
01165 uint32_t value2;
01166 int i;
01167
01168 device_p = (DevicePrivate *)malloc(sizeof(DevicePrivate));
01169 device->p = device_p;
01170
01171 uid = base58_decode(uid_str);
01172
01173 if (uid > 0xFFFFFFFF) {
01174
01175 value1 = uid & 0xFFFFFFFF;
01176 value2 = (uid >> 32) & 0xFFFFFFFF;
01177
01178 uid = (value1 & 0x00000FFF);
01179 uid |= (value1 & 0x0F000000) >> 12;
01180 uid |= (value2 & 0x0000003F) << 16;
01181 uid |= (value2 & 0x000F0000) << 6;
01182 uid |= (value2 & 0x3F000000) << 2;
01183 }
01184
01185 device_p->ref_count = 1;
01186
01187 device_p->uid = uid & 0xFFFFFFFF;
01188
01189 device_p->ipcon_p = ipcon_p;
01190
01191 device_p->api_version[0] = api_version_major;
01192 device_p->api_version[1] = api_version_minor;
01193 device_p->api_version[2] = api_version_release;
01194
01195
01196 mutex_create(&device_p->request_mutex);
01197
01198
01199 device_p->expected_response_function_id = 0;
01200 device_p->expected_response_sequence_number = 0;
01201
01202 mutex_create(&device_p->response_mutex);
01203
01204 memset(&device_p->response_packet, 0, sizeof(Packet));
01205
01206 event_create(&device_p->response_event);
01207
01208 for (i = 0; i < DEVICE_NUM_FUNCTION_IDS; i++) {
01209 device_p->response_expected[i] = DEVICE_RESPONSE_EXPECTED_INVALID_FUNCTION_ID;
01210 }
01211
01212 device_p->response_expected[IPCON_FUNCTION_ENUMERATE] = DEVICE_RESPONSE_EXPECTED_ALWAYS_FALSE;
01213 device_p->response_expected[IPCON_CALLBACK_ENUMERATE] = DEVICE_RESPONSE_EXPECTED_ALWAYS_FALSE;
01214
01215
01216 for (i = 0; i < DEVICE_NUM_FUNCTION_IDS; i++) {
01217 device_p->registered_callbacks[i] = NULL;
01218 device_p->registered_callback_user_data[i] = NULL;
01219 device_p->callback_wrappers[i] = NULL;
01220 }
01221
01222
01223 table_insert(&ipcon_p->devices, device_p->uid, device_p);
01224 }
01225
01226 void device_release(DevicePrivate *device_p) {
01227 IPConnectionPrivate *ipcon_p = device_p->ipcon_p;
01228
01229 mutex_lock(&ipcon_p->devices_ref_mutex);
01230
01231 --device_p->ref_count;
01232
01233 if (device_p->ref_count == 0) {
01234 device_destroy(device_p);
01235 }
01236
01237 mutex_unlock(&ipcon_p->devices_ref_mutex);
01238 }
01239
01240 int device_get_response_expected(DevicePrivate *device_p, uint8_t function_id,
01241 bool *ret_response_expected) {
01242 int flag = device_p->response_expected[function_id];
01243
01244 if (flag == DEVICE_RESPONSE_EXPECTED_INVALID_FUNCTION_ID) {
01245 return E_INVALID_PARAMETER;
01246 }
01247
01248 if (flag == DEVICE_RESPONSE_EXPECTED_ALWAYS_TRUE ||
01249 flag == DEVICE_RESPONSE_EXPECTED_TRUE) {
01250 *ret_response_expected = true;
01251 } else {
01252 *ret_response_expected = false;
01253 }
01254
01255 return E_OK;
01256 }
01257
01258 int device_set_response_expected(DevicePrivate *device_p, uint8_t function_id,
01259 bool response_expected) {
01260 int current_flag = device_p->response_expected[function_id];
01261
01262 if (current_flag != DEVICE_RESPONSE_EXPECTED_TRUE &&
01263 current_flag != DEVICE_RESPONSE_EXPECTED_FALSE) {
01264 return E_INVALID_PARAMETER;
01265 }
01266
01267 device_p->response_expected[function_id] =
01268 response_expected ? DEVICE_RESPONSE_EXPECTED_TRUE
01269 : DEVICE_RESPONSE_EXPECTED_FALSE;
01270
01271 return E_OK;
01272 }
01273
01274 int device_set_response_expected_all(DevicePrivate *device_p, bool response_expected) {
01275 int flag = response_expected ? DEVICE_RESPONSE_EXPECTED_TRUE
01276 : DEVICE_RESPONSE_EXPECTED_FALSE;
01277 int i;
01278
01279 for (i = 0; i < DEVICE_NUM_FUNCTION_IDS; ++i) {
01280 if (device_p->response_expected[i] == DEVICE_RESPONSE_EXPECTED_TRUE ||
01281 device_p->response_expected[i] == DEVICE_RESPONSE_EXPECTED_FALSE) {
01282 device_p->response_expected[i] = flag;
01283 }
01284 }
01285
01286 return E_OK;
01287 }
01288
01289 void device_register_callback(DevicePrivate *device_p, uint8_t id, void *callback,
01290 void *user_data) {
01291 device_p->registered_callbacks[id] = callback;
01292 device_p->registered_callback_user_data[id] = user_data;
01293 }
01294
01295 int device_get_api_version(DevicePrivate *device_p, uint8_t ret_api_version[3]) {
01296 ret_api_version[0] = device_p->api_version[0];
01297 ret_api_version[1] = device_p->api_version[1];
01298 ret_api_version[2] = device_p->api_version[2];
01299
01300 return E_OK;
01301 }
01302
01303 int device_send_request(DevicePrivate *device_p, Packet *request, Packet *response) {
01304 int ret = E_OK;
01305 uint8_t sequence_number = packet_header_get_sequence_number(&request->header);
01306 uint8_t response_expected = packet_header_get_response_expected(&request->header);
01307 uint8_t error_code;
01308
01309 if (response_expected) {
01310 mutex_lock(&device_p->request_mutex);
01311
01312 event_reset(&device_p->response_event);
01313
01314 device_p->expected_response_function_id = request->header.function_id;
01315 device_p->expected_response_sequence_number = sequence_number;
01316 }
01317
01318 ret = ipcon_send_request(device_p->ipcon_p, request);
01319
01320 if (ret != E_OK) {
01321 if (response_expected) {
01322 mutex_unlock(&device_p->request_mutex);
01323 }
01324
01325 return ret;
01326 }
01327
01328 if (response_expected) {
01329 if (event_wait(&device_p->response_event, device_p->ipcon_p->timeout) < 0) {
01330 ret = E_TIMEOUT;
01331 }
01332
01333 device_p->expected_response_function_id = 0;
01334 device_p->expected_response_sequence_number = 0;
01335
01336 event_reset(&device_p->response_event);
01337
01338 if (ret == E_OK) {
01339 mutex_lock(&device_p->response_mutex);
01340
01341 error_code = packet_header_get_error_code(&device_p->response_packet.header);
01342
01343 if (device_p->response_packet.header.function_id != request->header.function_id ||
01344 packet_header_get_sequence_number(&device_p->response_packet.header) != sequence_number) {
01345 ret = E_TIMEOUT;
01346 } else if (error_code == 0) {
01347
01348 if (response != NULL) {
01349 memcpy(response, &device_p->response_packet,
01350 device_p->response_packet.header.length);
01351 }
01352 } else if (error_code == 1) {
01353 ret = E_INVALID_PARAMETER;
01354 } else if (error_code == 2) {
01355 ret = E_NOT_SUPPORTED;
01356 } else {
01357 ret = E_UNKNOWN_ERROR_CODE;
01358 }
01359
01360 mutex_unlock(&device_p->response_mutex);
01361 }
01362
01363 mutex_unlock(&device_p->request_mutex);
01364 }
01365
01366 return ret;
01367 }
01368
01369
01370
01371
01372
01373
01374
01375 enum {
01376 BRICK_DAEMON_FUNCTION_GET_AUTHENTICATION_NONCE = 1,
01377 BRICK_DAEMON_FUNCTION_AUTHENTICATE = 2
01378 };
01379
01380 static void brickd_create(BrickDaemon *brickd, const char *uid, IPConnection *ipcon) {
01381 DevicePrivate *device_p;
01382
01383 device_create(brickd, uid, ipcon->p, 2, 0, 0);
01384
01385 device_p = brickd->p;
01386
01387 device_p->response_expected[BRICK_DAEMON_FUNCTION_GET_AUTHENTICATION_NONCE] = DEVICE_RESPONSE_EXPECTED_ALWAYS_TRUE;
01388 device_p->response_expected[BRICK_DAEMON_FUNCTION_AUTHENTICATE] = DEVICE_RESPONSE_EXPECTED_TRUE;
01389 }
01390
01391 static void brickd_destroy(BrickDaemon *brickd) {
01392 device_release(brickd->p);
01393 }
01394
01395 static int brickd_get_authentication_nonce(BrickDaemon *brickd, uint8_t ret_server_nonce[4]) {
01396 DevicePrivate *device_p = brickd->p;
01397 GetAuthenticationNonce request;
01398 GetAuthenticationNonceResponse response;
01399 int ret;
01400
01401 ret = packet_header_create(&request.header, sizeof(request), BRICK_DAEMON_FUNCTION_GET_AUTHENTICATION_NONCE, device_p->ipcon_p, device_p);
01402
01403 if (ret < 0) {
01404 return ret;
01405 }
01406
01407 ret = device_send_request(device_p, (Packet *)&request, (Packet *)&response);
01408
01409 if (ret < 0) {
01410 return ret;
01411 }
01412
01413 memcpy(ret_server_nonce, response.server_nonce, 4 * sizeof(uint8_t));
01414
01415 return ret;
01416 }
01417
01418 static int brickd_authenticate(BrickDaemon *brickd, uint8_t client_nonce[4], uint8_t digest[20]) {
01419 DevicePrivate *device_p = brickd->p;
01420 Authenticate request;
01421 int ret;
01422
01423 ret = packet_header_create(&request.header, sizeof(request), BRICK_DAEMON_FUNCTION_AUTHENTICATE, device_p->ipcon_p, device_p);
01424
01425 if (ret < 0) {
01426 return ret;
01427 }
01428
01429 memcpy(request.client_nonce, client_nonce, 4 * sizeof(uint8_t));
01430 memcpy(request.digest, digest, 20 * sizeof(uint8_t));
01431
01432 ret = device_send_request(device_p, (Packet *)&request, NULL);
01433
01434 return ret;
01435 }
01436
01437
01438
01439
01440
01441
01442
01443 struct _CallbackContext {
01444 IPConnectionPrivate *ipcon_p;
01445 Queue queue;
01446 Thread thread;
01447 Mutex mutex;
01448 bool packet_dispatch_allowed;
01449 };
01450
01451 static int ipcon_connect_unlocked(IPConnectionPrivate *ipcon_p, bool is_auto_reconnect);
01452 static void ipcon_disconnect_unlocked(IPConnectionPrivate *ipcon_p);
01453
01454 static DevicePrivate *ipcon_acquire_device(IPConnectionPrivate *ipcon_p, uint32_t uid) {
01455 DevicePrivate *device_p;
01456
01457 mutex_lock(&ipcon_p->devices_ref_mutex);
01458
01459 device_p = (DevicePrivate *)table_get(&ipcon_p->devices, uid);
01460
01461 if (device_p != NULL) {
01462 ++device_p->ref_count;
01463 }
01464
01465 mutex_unlock(&ipcon_p->devices_ref_mutex);
01466
01467 return device_p;
01468 }
01469
01470 static void ipcon_dispatch_meta(IPConnectionPrivate *ipcon_p, Meta *meta) {
01471 ConnectedCallbackFunction connected_callback_function;
01472 DisconnectedCallbackFunction disconnected_callback_function;
01473 void *user_data;
01474 bool retry;
01475
01476 if (meta->function_id == IPCON_CALLBACK_CONNECTED) {
01477 if (ipcon_p->registered_callbacks[IPCON_CALLBACK_CONNECTED] != NULL) {
01478 *(void **)(&connected_callback_function) = ipcon_p->registered_callbacks[IPCON_CALLBACK_CONNECTED];
01479 user_data = ipcon_p->registered_callback_user_data[IPCON_CALLBACK_CONNECTED];
01480
01481 connected_callback_function(meta->parameter, user_data);
01482 }
01483 } else if (meta->function_id == IPCON_CALLBACK_DISCONNECTED) {
01484
01485
01486
01487 if (meta->parameter != IPCON_DISCONNECT_REASON_REQUEST) {
01488 mutex_lock(&ipcon_p->socket_mutex);
01489
01490
01491
01492 if (ipcon_p->socket != NULL && ipcon_p->socket_id == meta->socket_id) {
01493
01494 event_set(&ipcon_p->disconnect_probe_event);
01495 thread_join(&ipcon_p->disconnect_probe_thread);
01496 thread_destroy(&ipcon_p->disconnect_probe_thread);
01497
01498
01499 socket_destroy(ipcon_p->socket);
01500 free(ipcon_p->socket);
01501 ipcon_p->socket = NULL;
01502 }
01503
01504 mutex_unlock(&ipcon_p->socket_mutex);
01505 }
01506
01507
01508
01509
01510 thread_sleep(100);
01511
01512 if (ipcon_p->registered_callbacks[IPCON_CALLBACK_DISCONNECTED] != NULL) {
01513 *(void **)(&disconnected_callback_function) = ipcon_p->registered_callbacks[IPCON_CALLBACK_DISCONNECTED];
01514 user_data = ipcon_p->registered_callback_user_data[IPCON_CALLBACK_DISCONNECTED];
01515
01516 disconnected_callback_function(meta->parameter, user_data);
01517 }
01518
01519 if (meta->parameter != IPCON_DISCONNECT_REASON_REQUEST &&
01520 ipcon_p->auto_reconnect && ipcon_p->auto_reconnect_allowed) {
01521 ipcon_p->auto_reconnect_pending = true;
01522 retry = true;
01523
01524
01525
01526 while (retry) {
01527 retry = false;
01528
01529 mutex_lock(&ipcon_p->socket_mutex);
01530
01531 if (ipcon_p->auto_reconnect_allowed && ipcon_p->socket == NULL) {
01532 if (ipcon_connect_unlocked(ipcon_p, true) < 0) {
01533 retry = true;
01534 }
01535 } else {
01536 ipcon_p->auto_reconnect_pending = false;
01537 }
01538
01539 mutex_unlock(&ipcon_p->socket_mutex);
01540
01541 if (retry) {
01542
01543
01544 thread_sleep(100);
01545 }
01546 }
01547 }
01548 }
01549 }
01550
01551 static void ipcon_dispatch_packet(IPConnectionPrivate *ipcon_p, Packet *packet) {
01552 EnumerateCallbackFunction enumerate_callback_function;
01553 void *user_data;
01554 EnumerateCallback *enumerate_callback;
01555 DevicePrivate *device_p;
01556 CallbackWrapperFunction callback_wrapper_function;
01557
01558 if (packet->header.function_id == IPCON_CALLBACK_ENUMERATE) {
01559 if (ipcon_p->registered_callbacks[IPCON_CALLBACK_ENUMERATE] != NULL) {
01560 *(void **)(&enumerate_callback_function) = ipcon_p->registered_callbacks[IPCON_CALLBACK_ENUMERATE];
01561 user_data = ipcon_p->registered_callback_user_data[IPCON_CALLBACK_ENUMERATE];
01562 enumerate_callback = (EnumerateCallback *)packet;
01563
01564 enumerate_callback_function(enumerate_callback->uid,
01565 enumerate_callback->connected_uid,
01566 enumerate_callback->position,
01567 enumerate_callback->hardware_version,
01568 enumerate_callback->firmware_version,
01569 leconvert_uint16_from(enumerate_callback->device_identifier),
01570 enumerate_callback->enumeration_type,
01571 user_data);
01572 }
01573 } else {
01574 device_p = ipcon_acquire_device(ipcon_p, packet->header.uid);
01575
01576 if (device_p == NULL) {
01577 return;
01578 }
01579
01580 callback_wrapper_function = device_p->callback_wrappers[packet->header.function_id];
01581
01582 if (callback_wrapper_function == NULL) {
01583 device_release(device_p);
01584
01585 return;
01586 }
01587
01588 callback_wrapper_function(device_p, packet);
01589
01590 device_release(device_p);
01591 }
01592 }
01593
01594 static void ipcon_callback_loop(void *opaque) {
01595 CallbackContext *callback = (CallbackContext *)opaque;
01596 int kind;
01597 void *data;
01598
01599 while (true) {
01600 if (queue_get(&callback->queue, &kind, &data) < 0) {
01601
01602 break;
01603 }
01604
01605
01606
01607
01608
01609 if (kind == QUEUE_KIND_EXIT) {
01610
01611 break;
01612 } else if (kind == QUEUE_KIND_META) {
01613 ipcon_dispatch_meta(callback->ipcon_p, (Meta *)data);
01614 } else if (kind == QUEUE_KIND_PACKET) {
01615
01616 if (callback->packet_dispatch_allowed) {
01617 ipcon_dispatch_packet(callback->ipcon_p, (Packet *)data);
01618 }
01619 }
01620
01621
01622
01623 free(data);
01624 }
01625
01626
01627 mutex_destroy(&callback->mutex);
01628 queue_destroy(&callback->queue);
01629 thread_destroy(&callback->thread);
01630
01631 free(callback);
01632 }
01633
01634
01635 static void ipcon_handle_disconnect_by_peer(IPConnectionPrivate *ipcon_p,
01636 uint8_t disconnect_reason,
01637 uint64_t socket_id,
01638 bool disconnect_immediately) {
01639 Meta *meta;
01640
01641 ipcon_p->auto_reconnect_allowed = true;
01642
01643 if (disconnect_immediately) {
01644 ipcon_disconnect_unlocked(ipcon_p);
01645 }
01646
01647 meta = (Meta *)malloc(sizeof(Meta));
01648 meta->function_id = IPCON_CALLBACK_DISCONNECTED;
01649 meta->parameter = disconnect_reason;
01650 meta->socket_id = socket_id;
01651
01652 queue_put(&ipcon_p->callback->queue, QUEUE_KIND_META, meta);
01653 }
01654
01655 enum {
01656 IPCON_DISCONNECT_PROBE_INTERVAL = 5000
01657 };
01658
01659 enum {
01660 IPCON_FUNCTION_DISCONNECT_PROBE = 128
01661 };
01662
01663
01664
01665 static void ipcon_disconnect_probe_loop(void *opaque) {
01666 IPConnectionPrivate *ipcon_p = (IPConnectionPrivate *)opaque;
01667 PacketHeader disconnect_probe;
01668
01669 packet_header_create(&disconnect_probe, sizeof(PacketHeader),
01670 IPCON_FUNCTION_DISCONNECT_PROBE, ipcon_p, NULL);
01671
01672 while (event_wait(&ipcon_p->disconnect_probe_event,
01673 IPCON_DISCONNECT_PROBE_INTERVAL) < 0) {
01674 if (ipcon_p->disconnect_probe_flag) {
01675
01676 if (socket_send(ipcon_p->socket, &disconnect_probe,
01677 disconnect_probe.length) < 0) {
01678 ipcon_handle_disconnect_by_peer(ipcon_p, IPCON_DISCONNECT_REASON_ERROR,
01679 ipcon_p->socket_id, false);
01680 break;
01681 }
01682 } else {
01683 ipcon_p->disconnect_probe_flag = true;
01684 }
01685 }
01686 }
01687
01688 static void ipcon_handle_response(IPConnectionPrivate *ipcon_p, Packet *response) {
01689 DevicePrivate *device_p;
01690 uint8_t sequence_number = packet_header_get_sequence_number(&response->header);
01691 Packet *callback;
01692
01693 ipcon_p->disconnect_probe_flag = false;
01694
01695 response->header.uid = leconvert_uint32_from(response->header.uid);
01696
01697 if (sequence_number == 0 &&
01698 response->header.function_id == IPCON_CALLBACK_ENUMERATE) {
01699 if (ipcon_p->registered_callbacks[IPCON_CALLBACK_ENUMERATE] != NULL) {
01700 callback = (Packet *)malloc(response->header.length);
01701
01702 memcpy(callback, response, response->header.length);
01703 queue_put(&ipcon_p->callback->queue, QUEUE_KIND_PACKET, callback);
01704 }
01705
01706 return;
01707 }
01708
01709 device_p = ipcon_acquire_device(ipcon_p, response->header.uid);
01710
01711 if (device_p == NULL) {
01712
01713 return;
01714 }
01715
01716 if (sequence_number == 0) {
01717 if (device_p->registered_callbacks[response->header.function_id] != NULL) {
01718 callback = (Packet *)malloc(response->header.length);
01719
01720 memcpy(callback, response, response->header.length);
01721 queue_put(&ipcon_p->callback->queue, QUEUE_KIND_PACKET, callback);
01722 }
01723
01724 device_release(device_p);
01725
01726 return;
01727 }
01728
01729 if (device_p->expected_response_function_id == response->header.function_id &&
01730 device_p->expected_response_sequence_number == sequence_number) {
01731 mutex_lock(&device_p->response_mutex);
01732 memcpy(&device_p->response_packet, response, response->header.length);
01733 mutex_unlock(&device_p->response_mutex);
01734
01735 event_set(&device_p->response_event);
01736
01737 device_release(device_p);
01738
01739 return;
01740 }
01741
01742 device_release(device_p);
01743
01744
01745 }
01746
01747
01748
01749 static void ipcon_receive_loop(void *opaque) {
01750 IPConnectionPrivate *ipcon_p = (IPConnectionPrivate *)opaque;
01751 uint64_t socket_id = ipcon_p->socket_id;
01752 Packet pending_data[10];
01753 int pending_length = 0;
01754 int length;
01755 uint8_t disconnect_reason;
01756
01757 while (ipcon_p->receive_flag) {
01758 length = socket_receive(ipcon_p->socket, (uint8_t *)pending_data + pending_length,
01759 sizeof(pending_data) - pending_length);
01760
01761 if (!ipcon_p->receive_flag) {
01762 return;
01763 }
01764
01765 if (length <= 0) {
01766 if (length < 0 && errno == EINTR) {
01767 continue;
01768 }
01769
01770 if (length == 0) {
01771 disconnect_reason = IPCON_DISCONNECT_REASON_SHUTDOWN;
01772 } else {
01773 disconnect_reason = IPCON_DISCONNECT_REASON_ERROR;
01774 }
01775
01776 ipcon_handle_disconnect_by_peer(ipcon_p, disconnect_reason, socket_id, false);
01777 return;
01778 }
01779
01780 pending_length += length;
01781
01782 while (ipcon_p->receive_flag) {
01783 if (pending_length < 8) {
01784
01785 break;
01786 }
01787
01788 length = pending_data[0].header.length;
01789
01790 if (pending_length < length) {
01791
01792 break;
01793 }
01794
01795 ipcon_handle_response(ipcon_p, pending_data);
01796
01797 memmove(pending_data, (uint8_t *)pending_data + length,
01798 pending_length - length);
01799 pending_length -= length;
01800 }
01801 }
01802 }
01803
01804
01805 static int ipcon_connect_unlocked(IPConnectionPrivate *ipcon_p, bool is_auto_reconnect) {
01806 struct hostent *entity;
01807 struct sockaddr_in address;
01808 uint8_t connect_reason;
01809 Meta *meta;
01810
01811
01812 if (ipcon_p->callback == NULL) {
01813 ipcon_p->callback = (CallbackContext *)malloc(sizeof(CallbackContext));
01814
01815 ipcon_p->callback->ipcon_p = ipcon_p;
01816 ipcon_p->callback->packet_dispatch_allowed = false;
01817
01818 queue_create(&ipcon_p->callback->queue);
01819 mutex_create(&ipcon_p->callback->mutex);
01820
01821 if (thread_create(&ipcon_p->callback->thread, ipcon_callback_loop,
01822 ipcon_p->callback) < 0) {
01823 mutex_destroy(&ipcon_p->callback->mutex);
01824 queue_destroy(&ipcon_p->callback->queue);
01825
01826 free(ipcon_p->callback);
01827 ipcon_p->callback = NULL;
01828
01829 return E_NO_THREAD;
01830 }
01831 }
01832
01833
01834 entity = gethostbyname(ipcon_p->host);
01835
01836 if (entity == NULL) {
01837
01838 if (!is_auto_reconnect) {
01839 queue_put(&ipcon_p->callback->queue, QUEUE_KIND_EXIT, NULL);
01840
01841 if (!thread_is_current(&ipcon_p->callback->thread)) {
01842 thread_join(&ipcon_p->callback->thread);
01843 }
01844
01845 ipcon_p->callback = NULL;
01846 }
01847
01848 return E_HOSTNAME_INVALID;
01849 }
01850
01851 memset(&address, 0, sizeof(struct sockaddr_in));
01852 memcpy(&address.sin_addr, entity->h_addr_list[0], entity->h_length);
01853
01854 address.sin_family = AF_INET;
01855 address.sin_port = htons(ipcon_p->port);
01856
01857 ipcon_p->socket = (Socket *)malloc(sizeof(Socket));
01858
01859 if (socket_create(ipcon_p->socket, AF_INET, SOCK_STREAM, 0) < 0) {
01860
01861 if (!is_auto_reconnect) {
01862 queue_put(&ipcon_p->callback->queue, QUEUE_KIND_EXIT, NULL);
01863
01864 if (!thread_is_current(&ipcon_p->callback->thread)) {
01865 thread_join(&ipcon_p->callback->thread);
01866 }
01867
01868 ipcon_p->callback = NULL;
01869 }
01870
01871
01872 free(ipcon_p->socket);
01873 ipcon_p->socket = NULL;
01874
01875 return E_NO_STREAM_SOCKET;
01876 }
01877
01878 if (socket_connect(ipcon_p->socket, &address, sizeof(address)) < 0) {
01879
01880 if (!is_auto_reconnect) {
01881 queue_put(&ipcon_p->callback->queue, QUEUE_KIND_EXIT, NULL);
01882
01883 if (!thread_is_current(&ipcon_p->callback->thread)) {
01884 thread_join(&ipcon_p->callback->thread);
01885 }
01886
01887 ipcon_p->callback = NULL;
01888 }
01889
01890
01891 socket_destroy(ipcon_p->socket);
01892 free(ipcon_p->socket);
01893 ipcon_p->socket = NULL;
01894
01895 return E_NO_CONNECT;
01896 }
01897
01898 ++ipcon_p->socket_id;
01899
01900
01901 ipcon_p->disconnect_probe_flag = true;
01902
01903 event_reset(&ipcon_p->disconnect_probe_event);
01904
01905 if (thread_create(&ipcon_p->disconnect_probe_thread,
01906 ipcon_disconnect_probe_loop, ipcon_p) < 0) {
01907
01908 if (!is_auto_reconnect) {
01909 queue_put(&ipcon_p->callback->queue, QUEUE_KIND_EXIT, NULL);
01910
01911 if (!thread_is_current(&ipcon_p->callback->thread)) {
01912 thread_join(&ipcon_p->callback->thread);
01913 }
01914
01915 ipcon_p->callback = NULL;
01916 }
01917
01918
01919 socket_destroy(ipcon_p->socket);
01920 free(ipcon_p->socket);
01921 ipcon_p->socket = NULL;
01922
01923 return E_NO_THREAD;
01924 }
01925
01926
01927 ipcon_p->receive_flag = true;
01928 ipcon_p->callback->packet_dispatch_allowed = true;
01929
01930 if (thread_create(&ipcon_p->receive_thread, ipcon_receive_loop, ipcon_p) < 0) {
01931
01932 ipcon_disconnect_unlocked(ipcon_p);
01933
01934
01935 if (!is_auto_reconnect) {
01936 queue_put(&ipcon_p->callback->queue, QUEUE_KIND_EXIT, NULL);
01937
01938 if (!thread_is_current(&ipcon_p->callback->thread)) {
01939 thread_join(&ipcon_p->callback->thread);
01940 }
01941
01942 ipcon_p->callback = NULL;
01943 }
01944
01945 return E_NO_THREAD;
01946 }
01947
01948 ipcon_p->auto_reconnect_allowed = false;
01949 ipcon_p->auto_reconnect_pending = false;
01950
01951
01952 if (is_auto_reconnect) {
01953 connect_reason = IPCON_CONNECT_REASON_AUTO_RECONNECT;
01954 } else {
01955 connect_reason = IPCON_CONNECT_REASON_REQUEST;
01956 }
01957
01958 meta = (Meta *)malloc(sizeof(Meta));
01959 meta->function_id = IPCON_CALLBACK_CONNECTED;
01960 meta->parameter = connect_reason;
01961 meta->socket_id = 0;
01962
01963 queue_put(&ipcon_p->callback->queue, QUEUE_KIND_META, meta);
01964
01965 return E_OK;
01966 }
01967
01968
01969 static void ipcon_disconnect_unlocked(IPConnectionPrivate *ipcon_p) {
01970
01971 event_set(&ipcon_p->disconnect_probe_event);
01972 thread_join(&ipcon_p->disconnect_probe_thread);
01973 thread_destroy(&ipcon_p->disconnect_probe_thread);
01974
01975
01976
01977
01978 if (!thread_is_current(&ipcon_p->callback->thread)) {
01979
01980
01981
01982
01983 ipcon_p->callback->packet_dispatch_allowed = false;
01984
01985
01986 } else {
01987 ipcon_p->callback->packet_dispatch_allowed = false;
01988 }
01989
01990
01991 if (ipcon_p->receive_flag) {
01992 ipcon_p->receive_flag = false;
01993
01994 socket_shutdown(ipcon_p->socket);
01995
01996 thread_join(&ipcon_p->receive_thread);
01997 thread_destroy(&ipcon_p->receive_thread);
01998 }
01999
02000
02001 socket_destroy(ipcon_p->socket);
02002 free(ipcon_p->socket);
02003 ipcon_p->socket = NULL;
02004 }
02005
02006 static int ipcon_send_request(IPConnectionPrivate *ipcon_p, Packet *request) {
02007 int ret = E_OK;
02008
02009 mutex_lock(&ipcon_p->socket_mutex);
02010
02011 if (ipcon_p->socket == NULL) {
02012 ret = E_NOT_CONNECTED;
02013 }
02014
02015 if (ret == E_OK) {
02016 if (socket_send(ipcon_p->socket, request, request->header.length) < 0) {
02017 ipcon_handle_disconnect_by_peer(ipcon_p, IPCON_DISCONNECT_REASON_ERROR,
02018 0, true);
02019
02020 ret = E_NOT_CONNECTED;
02021 } else {
02022 ipcon_p->disconnect_probe_flag = false;
02023 }
02024 }
02025
02026 mutex_unlock(&ipcon_p->socket_mutex);
02027
02028 return ret;
02029 }
02030
02031 void ipcon_create(IPConnection *ipcon) {
02032 IPConnectionPrivate *ipcon_p;
02033 int i;
02034
02035 ipcon_p = (IPConnectionPrivate *)malloc(sizeof(IPConnectionPrivate));
02036 ipcon->p = ipcon_p;
02037
02038 #ifdef _WIN32
02039 ipcon_p->wsa_startup_done = false;
02040 #endif
02041
02042 ipcon_p->host = NULL;
02043 ipcon_p->port = 0;
02044
02045 ipcon_p->timeout = 2500;
02046
02047 ipcon_p->auto_reconnect = true;
02048 ipcon_p->auto_reconnect_allowed = false;
02049 ipcon_p->auto_reconnect_pending = false;
02050
02051 mutex_create(&ipcon_p->sequence_number_mutex);
02052 ipcon_p->next_sequence_number = 0;
02053
02054 mutex_create(&ipcon_p->authentication_mutex);
02055 ipcon_p->next_authentication_nonce = 0;
02056
02057 mutex_create(&ipcon_p->devices_ref_mutex);
02058 table_create(&ipcon_p->devices);
02059
02060 for (i = 0; i < IPCON_NUM_CALLBACK_IDS; ++i) {
02061 ipcon_p->registered_callbacks[i] = NULL;
02062 ipcon_p->registered_callback_user_data[i] = NULL;
02063 }
02064
02065 mutex_create(&ipcon_p->socket_mutex);
02066 ipcon_p->socket = NULL;
02067 ipcon_p->socket_id = 0;
02068
02069 ipcon_p->receive_flag = false;
02070
02071 ipcon_p->callback = NULL;
02072
02073 ipcon_p->disconnect_probe_flag = false;
02074 event_create(&ipcon_p->disconnect_probe_event);
02075
02076 semaphore_create(&ipcon_p->wait);
02077
02078 brickd_create(&ipcon_p->brickd, "2", ipcon);
02079 }
02080
02081 void ipcon_destroy(IPConnection *ipcon) {
02082 IPConnectionPrivate *ipcon_p = ipcon->p;
02083
02084 ipcon_disconnect(ipcon);
02085
02086 brickd_destroy(&ipcon_p->brickd);
02087
02088 mutex_destroy(&ipcon_p->authentication_mutex);
02089
02090 mutex_destroy(&ipcon_p->sequence_number_mutex);
02091
02092 table_destroy(&ipcon_p->devices);
02093 mutex_destroy(&ipcon_p->devices_ref_mutex);
02094
02095 mutex_destroy(&ipcon_p->socket_mutex);
02096
02097 event_destroy(&ipcon_p->disconnect_probe_event);
02098
02099 semaphore_destroy(&ipcon_p->wait);
02100
02101 free(ipcon_p->host);
02102
02103 free(ipcon_p);
02104 }
02105
02106 int ipcon_connect(IPConnection *ipcon, const char *host, uint16_t port) {
02107 IPConnectionPrivate *ipcon_p = ipcon->p;
02108 int ret;
02109 #ifdef _WIN32
02110 WSADATA wsa_data;
02111 #endif
02112
02113 mutex_lock(&ipcon_p->socket_mutex);
02114
02115 #ifdef _WIN32
02116 if (!ipcon_p->wsa_startup_done) {
02117 if (WSAStartup(MAKEWORD(2, 2), &wsa_data) != 0) {
02118 mutex_unlock(&ipcon_p->socket_mutex);
02119
02120 return E_NO_STREAM_SOCKET;
02121 }
02122
02123 ipcon_p->wsa_startup_done = true;
02124 }
02125 #endif
02126
02127 if (ipcon_p->socket != NULL) {
02128 mutex_unlock(&ipcon_p->socket_mutex);
02129
02130 return E_ALREADY_CONNECTED;
02131 }
02132
02133 free(ipcon_p->host);
02134
02135 ipcon_p->host = strdup(host);
02136 ipcon_p->port = port;
02137
02138 ret = ipcon_connect_unlocked(ipcon_p, false);
02139
02140 mutex_unlock(&ipcon_p->socket_mutex);
02141
02142 return ret;
02143 }
02144
02145 int ipcon_disconnect(IPConnection *ipcon) {
02146 IPConnectionPrivate *ipcon_p = ipcon->p;
02147 CallbackContext *callback;
02148 Meta *meta;
02149
02150 mutex_lock(&ipcon_p->socket_mutex);
02151
02152 ipcon_p->auto_reconnect_allowed = false;
02153
02154 if (ipcon_p->auto_reconnect_pending) {
02155
02156 ipcon_p->auto_reconnect_pending = false;
02157 } else {
02158 if (ipcon_p->socket == NULL) {
02159 mutex_unlock(&ipcon_p->socket_mutex);
02160
02161 return E_NOT_CONNECTED;
02162 }
02163
02164 ipcon_disconnect_unlocked(ipcon_p);
02165 }
02166
02167
02168 callback = ipcon_p->callback;
02169 ipcon_p->callback = NULL;
02170
02171 mutex_unlock(&ipcon_p->socket_mutex);
02172
02173
02174
02175 meta = (Meta *)malloc(sizeof(Meta));
02176 meta->function_id = IPCON_CALLBACK_DISCONNECTED;
02177 meta->parameter = IPCON_DISCONNECT_REASON_REQUEST;
02178 meta->socket_id = 0;
02179
02180 queue_put(&callback->queue, QUEUE_KIND_META, meta);
02181 queue_put(&callback->queue, QUEUE_KIND_EXIT, NULL);
02182
02183 if (!thread_is_current(&callback->thread)) {
02184 thread_join(&callback->thread);
02185 }
02186
02187
02188
02189
02190 return E_OK;
02191 }
02192
02193 int ipcon_authenticate(IPConnection *ipcon, const char secret[64]) {
02194 IPConnectionPrivate *ipcon_p = ipcon->p;
02195 int ret;
02196 uint32_t nonces[2];
02197 uint8_t digest[SHA1_DIGEST_LENGTH];
02198
02199 mutex_lock(&ipcon_p->authentication_mutex);
02200
02201 if (ipcon_p->next_authentication_nonce == 0) {
02202 ipcon_p->next_authentication_nonce = get_random_uint32();
02203 }
02204
02205 ret = brickd_get_authentication_nonce(&ipcon_p->brickd, (uint8_t *)nonces);
02206
02207 if (ret < 0) {
02208 mutex_unlock(&ipcon_p->authentication_mutex);
02209
02210 return ret;
02211 }
02212
02213 nonces[1] = ipcon_p->next_authentication_nonce++;
02214
02215 hmac_sha1((uint8_t *)secret, string_length(secret, IPCON_MAX_SECRET_LENGTH),
02216 (uint8_t *)nonces, sizeof(nonces), digest);
02217
02218 ret = brickd_authenticate(&ipcon_p->brickd, (uint8_t *)&nonces[1], digest);
02219
02220 if (ret < 0) {
02221 mutex_unlock(&ipcon_p->authentication_mutex);
02222
02223 return ret;
02224 }
02225
02226 mutex_unlock(&ipcon_p->authentication_mutex);
02227
02228 return E_OK;
02229 }
02230
02231 int ipcon_get_connection_state(IPConnection *ipcon) {
02232 IPConnectionPrivate *ipcon_p = ipcon->p;
02233
02234 if (ipcon_p->socket != NULL) {
02235 return IPCON_CONNECTION_STATE_CONNECTED;
02236 } else if (ipcon_p->auto_reconnect_pending) {
02237 return IPCON_CONNECTION_STATE_PENDING;
02238 } else {
02239 return IPCON_CONNECTION_STATE_DISCONNECTED;
02240 }
02241 }
02242
02243 void ipcon_set_auto_reconnect(IPConnection *ipcon, bool auto_reconnect) {
02244 IPConnectionPrivate *ipcon_p = ipcon->p;
02245
02246 ipcon_p->auto_reconnect = auto_reconnect;
02247
02248 if (!ipcon_p->auto_reconnect) {
02249
02250 ipcon_p->auto_reconnect_allowed = false;
02251 }
02252 }
02253
02254 bool ipcon_get_auto_reconnect(IPConnection *ipcon) {
02255 return ipcon->p->auto_reconnect;
02256 }
02257
02258 void ipcon_set_timeout(IPConnection *ipcon, uint32_t timeout) {
02259 ipcon->p->timeout = timeout;
02260 }
02261
02262 uint32_t ipcon_get_timeout(IPConnection *ipcon) {
02263 return ipcon->p->timeout;
02264 }
02265
02266 int ipcon_enumerate(IPConnection *ipcon) {
02267 IPConnectionPrivate *ipcon_p = ipcon->p;
02268 Enumerate enumerate;
02269 int ret;
02270
02271 ret = packet_header_create(&enumerate.header, sizeof(Enumerate),
02272 IPCON_FUNCTION_ENUMERATE, ipcon_p, NULL);
02273
02274 if (ret < 0) {
02275 return ret;
02276 }
02277
02278 return ipcon_send_request(ipcon_p, (Packet *)&enumerate);
02279 }
02280
02281 void ipcon_wait(IPConnection *ipcon) {
02282 semaphore_acquire(&ipcon->p->wait);
02283 }
02284
02285 void ipcon_unwait(IPConnection *ipcon) {
02286 semaphore_release(&ipcon->p->wait);
02287 }
02288
02289 void ipcon_register_callback(IPConnection *ipcon, uint8_t id, void *callback,
02290 void *user_data) {
02291 IPConnectionPrivate *ipcon_p = ipcon->p;
02292
02293 ipcon_p->registered_callbacks[id] = callback;
02294 ipcon_p->registered_callback_user_data[id] = user_data;
02295 }
02296
02297 int packet_header_create(PacketHeader *header, uint8_t length,
02298 uint8_t function_id, IPConnectionPrivate *ipcon_p,
02299 DevicePrivate *device_p) {
02300 uint8_t sequence_number;
02301 bool response_expected = false;
02302 int ret = E_OK;
02303
02304 mutex_lock(&ipcon_p->sequence_number_mutex);
02305
02306 sequence_number = ipcon_p->next_sequence_number + 1;
02307 ipcon_p->next_sequence_number = sequence_number % 15;
02308
02309 mutex_unlock(&ipcon_p->sequence_number_mutex);
02310
02311 memset(header, 0, sizeof(PacketHeader));
02312
02313 if (device_p != NULL) {
02314 header->uid = leconvert_uint32_to(device_p->uid);
02315 }
02316
02317 header->length = length;
02318 header->function_id = function_id;
02319 packet_header_set_sequence_number(header, sequence_number);
02320
02321 if (device_p != NULL) {
02322 ret = device_get_response_expected(device_p, function_id, &response_expected);
02323 packet_header_set_response_expected(header, response_expected ? 1 : 0);
02324 }
02325
02326 return ret;
02327 }
02328
02329 uint8_t packet_header_get_sequence_number(PacketHeader *header) {
02330 return (header->sequence_number_and_options >> 4) & 0x0F;
02331 }
02332
02333 void packet_header_set_sequence_number(PacketHeader *header,
02334 uint8_t sequence_number) {
02335 header->sequence_number_and_options |= (sequence_number << 4) & 0xF0;
02336 }
02337
02338 uint8_t packet_header_get_response_expected(PacketHeader *header) {
02339 return (header->sequence_number_and_options >> 3) & 0x01;
02340 }
02341
02342 void packet_header_set_response_expected(PacketHeader *header,
02343 uint8_t response_expected) {
02344 header->sequence_number_and_options |= (response_expected << 3) & 0x08;
02345 }
02346
02347 uint8_t packet_header_get_error_code(PacketHeader *header) {
02348 return (header->error_code_and_future_use >> 6) & 0x03;
02349 }
02350
02351 int16_t leconvert_int16_to(int16_t native) {
02352 return leconvert_uint16_to(native);
02353 }
02354
02355 uint16_t leconvert_uint16_to(uint16_t native) {
02356 union {
02357 uint8_t bytes[2];
02358 uint16_t little;
02359 } c;
02360
02361 c.bytes[0] = (native >> 0) & 0xFF;
02362 c.bytes[1] = (native >> 8) & 0xFF;
02363
02364 return c.little;
02365 }
02366
02367 int32_t leconvert_int32_to(int32_t native) {
02368 return leconvert_uint32_to(native);
02369 }
02370
02371 uint32_t leconvert_uint32_to(uint32_t native) {
02372 union {
02373 uint8_t bytes[4];
02374 uint32_t little;
02375 } c;
02376
02377 c.bytes[0] = (native >> 0) & 0xFF;
02378 c.bytes[1] = (native >> 8) & 0xFF;
02379 c.bytes[2] = (native >> 16) & 0xFF;
02380 c.bytes[3] = (native >> 24) & 0xFF;
02381
02382 return c.little;
02383 }
02384
02385 int64_t leconvert_int64_to(int64_t native) {
02386 return leconvert_uint64_to(native);
02387 }
02388
02389 uint64_t leconvert_uint64_to(uint64_t native) {
02390 union {
02391 uint8_t bytes[8];
02392 uint64_t little;
02393 } c;
02394
02395 c.bytes[0] = (native >> 0) & 0xFF;
02396 c.bytes[1] = (native >> 8) & 0xFF;
02397 c.bytes[2] = (native >> 16) & 0xFF;
02398 c.bytes[3] = (native >> 24) & 0xFF;
02399 c.bytes[4] = (native >> 32) & 0xFF;
02400 c.bytes[5] = (native >> 40) & 0xFF;
02401 c.bytes[6] = (native >> 48) & 0xFF;
02402 c.bytes[7] = (native >> 56) & 0xFF;
02403
02404 return c.little;
02405 }
02406
02407 float leconvert_float_to(float native) {
02408 union {
02409 uint32_t u;
02410 float f;
02411 } c;
02412
02413 c.f = native;
02414 c.u = leconvert_uint32_to(c.u);
02415
02416 return c.f;
02417 }
02418
02419 int16_t leconvert_int16_from(int16_t little) {
02420 return leconvert_uint16_from(little);
02421 }
02422
02423 uint16_t leconvert_uint16_from(uint16_t little) {
02424 uint8_t *bytes = (uint8_t *)&little;
02425
02426 return ((uint16_t)bytes[1] << 8) |
02427 (uint16_t)bytes[0];
02428 }
02429
02430 int32_t leconvert_int32_from(int32_t little) {
02431 return leconvert_uint32_from(little);
02432 }
02433
02434 uint32_t leconvert_uint32_from(uint32_t little) {
02435 uint8_t *bytes = (uint8_t *)&little;
02436
02437 return ((uint32_t)bytes[3] << 24) |
02438 ((uint32_t)bytes[2] << 16) |
02439 ((uint32_t)bytes[1] << 8) |
02440 (uint32_t)bytes[0];
02441 }
02442
02443 int64_t leconvert_int64_from(int64_t little) {
02444 return leconvert_uint64_from(little);
02445 }
02446
02447 uint64_t leconvert_uint64_from(uint64_t little) {
02448 uint8_t *bytes = (uint8_t *)&little;
02449
02450 return ((uint64_t)bytes[7] << 56) |
02451 ((uint64_t)bytes[6] << 48) |
02452 ((uint64_t)bytes[5] << 40) |
02453 ((uint64_t)bytes[4] << 32) |
02454 ((uint64_t)bytes[3] << 24) |
02455 ((uint64_t)bytes[2] << 16) |
02456 ((uint64_t)bytes[1] << 8) |
02457 (uint64_t)bytes[0];
02458 }
02459
02460 float leconvert_float_from(float little) {
02461 union {
02462 uint32_t u;
02463 float f;
02464 } c;
02465
02466 c.f = little;
02467 c.u = leconvert_uint32_from(c.u);
02468
02469 return c.f;
02470 }
02471
02472 #ifdef __cplusplus
02473 }
02474 #endif