diff --git a/lib/crypto.c b/lib/crypto.c index 50605b32..6714255e 100644 --- a/lib/crypto.c +++ b/lib/crypto.c @@ -27,10 +27,10 @@ #include struct aes_ctx_s { - EVP_CIPHER_CTX *cipher_ctx; - uint8_t key[AES_128_BLOCK_SIZE]; - uint8_t iv[AES_128_BLOCK_SIZE]; - aes_direction_t direction; + EVP_CIPHER_CTX *cipher_ctx; + uint8_t key[AES_128_BLOCK_SIZE]; + uint8_t iv[AES_128_BLOCK_SIZE]; + aes_direction_t direction; uint8_t block_offset; }; @@ -39,85 +39,85 @@ uint8_t waste[AES_128_BLOCK_SIZE]; // Common AES utilities void handle_error(const char* location) { - long error = ERR_get_error(); + long error = ERR_get_error(); const char* error_str = ERR_error_string(error, NULL); printf("Crypto error at %s: %s\n", location, error_str); assert(false); } aes_ctx_t *aes_init(const uint8_t *key, const uint8_t *iv, const EVP_CIPHER *type, aes_direction_t direction) { - aes_ctx_t *ctx = malloc(sizeof(aes_ctx_t)); - assert(ctx != NULL); - ctx->cipher_ctx = EVP_CIPHER_CTX_new(); - assert(ctx->cipher_ctx != NULL); + aes_ctx_t *ctx = malloc(sizeof(aes_ctx_t)); + assert(ctx != NULL); + ctx->cipher_ctx = EVP_CIPHER_CTX_new(); + assert(ctx->cipher_ctx != NULL); - ctx->block_offset = 0; - ctx->direction = direction; + ctx->block_offset = 0; + ctx->direction = direction; - if (direction == AES_ENCRYPT) { - if (!EVP_EncryptInit_ex(ctx->cipher_ctx, type, NULL, key, iv)) { - handle_error(__func__); - } - } else { - if (!EVP_DecryptInit_ex(ctx->cipher_ctx, type, NULL, key, iv)) { - handle_error(__func__); - } - } + if (direction == AES_ENCRYPT) { + if (!EVP_EncryptInit_ex(ctx->cipher_ctx, type, NULL, key, iv)) { + handle_error(__func__); + } + } else { + if (!EVP_DecryptInit_ex(ctx->cipher_ctx, type, NULL, key, iv)) { + handle_error(__func__); + } + } - memcpy(ctx->key, key, AES_128_BLOCK_SIZE); - memcpy(ctx->iv, iv, AES_128_BLOCK_SIZE); - return ctx; + memcpy(ctx->key, key, AES_128_BLOCK_SIZE); + memcpy(ctx->iv, iv, AES_128_BLOCK_SIZE); + return ctx; } void aes_encrypt(aes_ctx_t *ctx, const uint8_t *in, uint8_t *out, int in_len) { - int out_len = 0; - if (!EVP_EncryptUpdate(ctx->cipher_ctx, out, &out_len, in, in_len)) { - handle_error(__func__); - } + int out_len = 0; + if (!EVP_EncryptUpdate(ctx->cipher_ctx, out, &out_len, in, in_len)) { + handle_error(__func__); + } - assert(out_len <= in_len); + assert(out_len <= in_len); } void aes_decrypt(aes_ctx_t *ctx, const uint8_t *in, uint8_t *out, int in_len) { - int out_len = 0; - if (!EVP_DecryptUpdate(ctx->cipher_ctx, out, &out_len, in, in_len)) { - handle_error(__func__); - } + int out_len = 0; + if (!EVP_DecryptUpdate(ctx->cipher_ctx, out, &out_len, in, in_len)) { + handle_error(__func__); + } - assert(out_len <= in_len); + assert(out_len <= in_len); } void aes_destroy(aes_ctx_t *ctx) { - if (ctx) { - EVP_CIPHER_CTX_free(ctx->cipher_ctx); - free(ctx); - } + if (ctx) { + EVP_CIPHER_CTX_free(ctx->cipher_ctx); + free(ctx); + } } void aes_reset(aes_ctx_t *ctx, const EVP_CIPHER *type, aes_direction_t direction) { - if (!EVP_CIPHER_CTX_reset(ctx->cipher_ctx)) { + if (!EVP_CIPHER_CTX_reset(ctx->cipher_ctx)) { handle_error(__func__); - } + } - if (direction == AES_ENCRYPT) { - if (!EVP_EncryptInit_ex(ctx->cipher_ctx, type, NULL, ctx->key, ctx->iv)) { - handle_error(__func__); - } - } else { - if (!EVP_DecryptInit_ex(ctx->cipher_ctx, type, NULL, ctx->key, ctx->iv)) { - handle_error(__func__); - } - } + if (direction == AES_ENCRYPT) { + if (!EVP_EncryptInit_ex(ctx->cipher_ctx, type, NULL, ctx->key, ctx->iv)) { + handle_error(__func__); + } + } else { + if (!EVP_DecryptInit_ex(ctx->cipher_ctx, type, NULL, ctx->key, ctx->iv)) { + handle_error(__func__); + } + } } // AES CTR aes_ctx_t *aes_ctr_init(const uint8_t *key, const uint8_t *iv) { - return aes_init(key, iv, EVP_aes_128_ctr(), AES_ENCRYPT); + return aes_init(key, iv, EVP_aes_128_ctr(), AES_ENCRYPT); } void aes_ctr_encrypt(aes_ctx_t *ctx, const uint8_t *in, uint8_t *out, int len) { - aes_encrypt(ctx, in, out, len); + aes_encrypt(ctx, in, out, len); ctx->block_offset = (ctx->block_offset + len) % AES_128_BLOCK_SIZE; } @@ -128,82 +128,82 @@ void aes_ctr_start_fresh_block(aes_ctx_t *ctx) { } void aes_ctr_decrypt(aes_ctx_t *ctx, const uint8_t *in, uint8_t *out, int len) { - aes_encrypt(ctx, in, out, len); + aes_encrypt(ctx, in, out, len); } void aes_ctr_reset(aes_ctx_t *ctx) { - aes_reset(ctx, EVP_aes_128_ctr(), AES_ENCRYPT); + aes_reset(ctx, EVP_aes_128_ctr(), AES_ENCRYPT); } void aes_ctr_destroy(aes_ctx_t *ctx) { - aes_destroy(ctx); + aes_destroy(ctx); } // AES CBC aes_ctx_t *aes_cbc_init(const uint8_t *key, const uint8_t *iv, aes_direction_t direction) { - return aes_init(key, iv, EVP_aes_128_cbc(), direction); + return aes_init(key, iv, EVP_aes_128_cbc(), direction); } void aes_cbc_encrypt(aes_ctx_t *ctx, const uint8_t *in, uint8_t *out, int len) { - assert(ctx->direction == AES_ENCRYPT); - aes_encrypt(ctx, in, out, len); + assert(ctx->direction == AES_ENCRYPT); + aes_encrypt(ctx, in, out, len); } void aes_cbc_decrypt(aes_ctx_t *ctx, const uint8_t *in, uint8_t *out, int len) { - assert(ctx->direction == AES_DECRYPT); - aes_decrypt(ctx, in, out, len); + assert(ctx->direction == AES_DECRYPT); + aes_decrypt(ctx, in, out, len); } void aes_cbc_reset(aes_ctx_t *ctx) { - aes_reset(ctx, EVP_aes_128_ctr(), ctx->direction); + aes_reset(ctx, EVP_aes_128_ctr(), ctx->direction); } void aes_cbc_destroy(aes_ctx_t *ctx) { - aes_destroy(ctx); + aes_destroy(ctx); } // SHA 512 struct sha_ctx_s { - EVP_MD_CTX *digest_ctx; + EVP_MD_CTX *digest_ctx; }; sha_ctx_t *sha_init() { - sha_ctx_t *ctx = malloc(sizeof(sha_ctx_t)); - assert(ctx != NULL); - ctx->digest_ctx = EVP_MD_CTX_new(); - assert(ctx->digest_ctx != NULL); + sha_ctx_t *ctx = malloc(sizeof(sha_ctx_t)); + assert(ctx != NULL); + ctx->digest_ctx = EVP_MD_CTX_new(); + assert(ctx->digest_ctx != NULL); - if (!EVP_DigestInit_ex(ctx->digest_ctx, EVP_sha512(), NULL)) { - handle_error(__func__); - } - return ctx; + if (!EVP_DigestInit_ex(ctx->digest_ctx, EVP_sha512(), NULL)) { + handle_error(__func__); + } + return ctx; } void sha_update(sha_ctx_t *ctx, const uint8_t *in, int len) { - if (!EVP_DigestUpdate(ctx->digest_ctx, in, len)) { - handle_error(__func__); - } + if (!EVP_DigestUpdate(ctx->digest_ctx, in, len)) { + handle_error(__func__); + } } void sha_final(sha_ctx_t *ctx, uint8_t *out, unsigned int *len) { - if (!EVP_DigestFinal_ex(ctx->digest_ctx, out, len)) { - handle_error(__func__); - } + if (!EVP_DigestFinal_ex(ctx->digest_ctx, out, len)) { + handle_error(__func__); + } } void sha_reset(sha_ctx_t *ctx) { - if (!EVP_MD_CTX_reset(ctx->digest_ctx) || - !EVP_DigestInit_ex(ctx->digest_ctx, EVP_sha512(), NULL)) { + if (!EVP_MD_CTX_reset(ctx->digest_ctx) || + !EVP_DigestInit_ex(ctx->digest_ctx, EVP_sha512(), NULL)) { - handle_error(__func__); - } + handle_error(__func__); + } } void sha_destroy(sha_ctx_t *ctx) { - if (ctx) { - EVP_MD_CTX_free(ctx->digest_ctx); - free(ctx); - } + if (ctx) { + EVP_MD_CTX_free(ctx->digest_ctx); + free(ctx); + } } diff --git a/lib/dnssd.c b/lib/dnssd.c index b09a8e55..cf66a38c 100644 --- a/lib/dnssd.c +++ b/lib/dnssd.c @@ -342,7 +342,7 @@ dnssd_register_airplay(dnssd_t *dnssd, unsigned short port) return 1; } -char * +char * dnssd_get_airplay_txt(dnssd_t *dnssd, int *length) { *length = dnssd->TXTRecordGetLength(&dnssd->airplay_record); diff --git a/lib/fairplay_playfair.c b/lib/fairplay_playfair.c index ee5586e7..ade48d9b 100755 --- a/lib/fairplay_playfair.c +++ b/lib/fairplay_playfair.c @@ -13,24 +13,24 @@ char reply_message[4][142] = {{0x46,0x50,0x4c,0x59,0x03,0x01,0x02,0x00,0x00,0x00 char fp_header[] = {0x46, 0x50, 0x4c, 0x59, 0x03, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x14}; struct fairplay_s { - logger_t *logger; + logger_t *logger; - unsigned char keymsg[164]; - unsigned int keymsglen; + unsigned char keymsg[164]; + unsigned int keymsglen; }; fairplay_t * fairplay_init(logger_t *logger) { - fairplay_t *fp; + fairplay_t *fp; - fp = calloc(1, sizeof(fairplay_t)); - if (!fp) { - return NULL; - } - fp->logger = logger; + fp = calloc(1, sizeof(fairplay_t)); + if (!fp) { + return NULL; + } + fp->logger = logger; - return fp; + return fp; } int @@ -72,16 +72,16 @@ fairplay_handshake(fairplay_t *fp, const unsigned char req[164], unsigned char r int fairplay_decrypt(fairplay_t *fp, const unsigned char input[72], unsigned char output[16]) { - if (fp->keymsglen != 164) { - return -1; - } + if (fp->keymsglen != 164) { + return -1; + } - playfair_decrypt(fp->keymsg, (unsigned char *) input, output); - return 0; + playfair_decrypt(fp->keymsg, (unsigned char *) input, output); + return 0; } void fairplay_destroy(fairplay_t *fp) { - free(fp); + free(fp); } diff --git a/lib/http_request.c b/lib/http_request.c index 694a7097..a9d2ca07 100755 --- a/lib/http_request.c +++ b/lib/http_request.c @@ -20,233 +20,233 @@ #include "http_parser.h" struct http_request_s { - http_parser parser; - http_parser_settings parser_settings; + http_parser parser; + http_parser_settings parser_settings; - const char *method; - char *url; + const char *method; + char *url; - char **headers; - int headers_size; - int headers_index; + char **headers; + int headers_size; + int headers_index; - char *data; - int datalen; + char *data; + int datalen; - int complete; + int complete; }; static int on_url(http_parser *parser, const char *at, size_t length) { - http_request_t *request = parser->data; - int urllen = request->url ? strlen(request->url) : 0; + http_request_t *request = parser->data; + int urllen = request->url ? strlen(request->url) : 0; - request->url = realloc(request->url, urllen+length+1); - assert(request->url); + request->url = realloc(request->url, urllen+length+1); + assert(request->url); - request->url[urllen] = '\0'; - strncat(request->url, at, length); - return 0; + request->url[urllen] = '\0'; + strncat(request->url, at, length); + return 0; } static int on_header_field(http_parser *parser, const char *at, size_t length) { - http_request_t *request = parser->data; - - /* Check if our index is a value */ - if (request->headers_index%2 == 1) { - request->headers_index++; - } - - /* Allocate space for new field-value pair */ - if (request->headers_index == request->headers_size) { - request->headers_size += 2; - request->headers = realloc(request->headers, - request->headers_size*sizeof(char*)); - assert(request->headers); - request->headers[request->headers_index] = NULL; - request->headers[request->headers_index+1] = NULL; - } - - /* Allocate space in the current header string */ - if (request->headers[request->headers_index] == NULL) { - request->headers[request->headers_index] = calloc(1, length+1); - } else { - request->headers[request->headers_index] = realloc( - request->headers[request->headers_index], - strlen(request->headers[request->headers_index])+length+1 - ); - } - assert(request->headers[request->headers_index]); - - strncat(request->headers[request->headers_index], at, length); - return 0; + http_request_t *request = parser->data; + + /* Check if our index is a value */ + if (request->headers_index%2 == 1) { + request->headers_index++; + } + + /* Allocate space for new field-value pair */ + if (request->headers_index == request->headers_size) { + request->headers_size += 2; + request->headers = realloc(request->headers, + request->headers_size*sizeof(char*)); + assert(request->headers); + request->headers[request->headers_index] = NULL; + request->headers[request->headers_index+1] = NULL; + } + + /* Allocate space in the current header string */ + if (request->headers[request->headers_index] == NULL) { + request->headers[request->headers_index] = calloc(1, length+1); + } else { + request->headers[request->headers_index] = realloc( + request->headers[request->headers_index], + strlen(request->headers[request->headers_index])+length+1 + ); + } + assert(request->headers[request->headers_index]); + + strncat(request->headers[request->headers_index], at, length); + return 0; } static int on_header_value(http_parser *parser, const char *at, size_t length) { - http_request_t *request = parser->data; + http_request_t *request = parser->data; - /* Check if our index is a field */ - if (request->headers_index%2 == 0) { - request->headers_index++; - } + /* Check if our index is a field */ + if (request->headers_index%2 == 0) { + request->headers_index++; + } - /* Allocate space in the current header string */ - if (request->headers[request->headers_index] == NULL) { - request->headers[request->headers_index] = calloc(1, length+1); - } else { - request->headers[request->headers_index] = realloc( - request->headers[request->headers_index], - strlen(request->headers[request->headers_index])+length+1 - ); - } - assert(request->headers[request->headers_index]); + /* Allocate space in the current header string */ + if (request->headers[request->headers_index] == NULL) { + request->headers[request->headers_index] = calloc(1, length+1); + } else { + request->headers[request->headers_index] = realloc( + request->headers[request->headers_index], + strlen(request->headers[request->headers_index])+length+1 + ); + } + assert(request->headers[request->headers_index]); - strncat(request->headers[request->headers_index], at, length); - return 0; + strncat(request->headers[request->headers_index], at, length); + return 0; } static int on_body(http_parser *parser, const char *at, size_t length) { - http_request_t *request = parser->data; + http_request_t *request = parser->data; - request->data = realloc(request->data, request->datalen+length); - assert(request->data); + request->data = realloc(request->data, request->datalen+length); + assert(request->data); - memcpy(request->data+request->datalen, at, length); - request->datalen += length; - return 0; + memcpy(request->data+request->datalen, at, length); + request->datalen += length; + return 0; } static int on_message_complete(http_parser *parser) { - http_request_t *request = parser->data; + http_request_t *request = parser->data; - request->method = http_method_str(request->parser.method); - request->complete = 1; - return 0; + request->method = http_method_str(request->parser.method); + request->complete = 1; + return 0; } http_request_t * http_request_init(void) { - http_request_t *request; + http_request_t *request; - request = calloc(1, sizeof(http_request_t)); - if (!request) { - return NULL; - } - http_parser_init(&request->parser, HTTP_REQUEST); - request->parser.data = request; + request = calloc(1, sizeof(http_request_t)); + if (!request) { + return NULL; + } + http_parser_init(&request->parser, HTTP_REQUEST); + request->parser.data = request; - request->parser_settings.on_url = &on_url; - request->parser_settings.on_header_field = &on_header_field; - request->parser_settings.on_header_value = &on_header_value; - request->parser_settings.on_body = &on_body; - request->parser_settings.on_message_complete = &on_message_complete; + request->parser_settings.on_url = &on_url; + request->parser_settings.on_header_field = &on_header_field; + request->parser_settings.on_header_value = &on_header_value; + request->parser_settings.on_body = &on_body; + request->parser_settings.on_message_complete = &on_message_complete; - return request; + return request; } void http_request_destroy(http_request_t *request) { - int i; + int i; - if (request) { - free(request->url); - for (i=0; iheaders_size; i++) { - free(request->headers[i]); - } - free(request->headers); - free(request->data); - free(request); - } + if (request) { + free(request->url); + for (i=0; iheaders_size; i++) { + free(request->headers[i]); + } + free(request->headers); + free(request->data); + free(request); + } } int http_request_add_data(http_request_t *request, const char *data, int datalen) { - int ret; + int ret; - assert(request); + assert(request); - ret = http_parser_execute(&request->parser, - &request->parser_settings, - data, datalen); - return ret; + ret = http_parser_execute(&request->parser, + &request->parser_settings, + data, datalen); + return ret; } int http_request_is_complete(http_request_t *request) { - assert(request); - return request->complete; + assert(request); + return request->complete; } int http_request_has_error(http_request_t *request) { - assert(request); - return (HTTP_PARSER_ERRNO(&request->parser) != HPE_OK); + assert(request); + return (HTTP_PARSER_ERRNO(&request->parser) != HPE_OK); } const char * http_request_get_error_name(http_request_t *request) { - assert(request); - return http_errno_name(HTTP_PARSER_ERRNO(&request->parser)); + assert(request); + return http_errno_name(HTTP_PARSER_ERRNO(&request->parser)); } const char * http_request_get_error_description(http_request_t *request) { - assert(request); - return http_errno_description(HTTP_PARSER_ERRNO(&request->parser)); + assert(request); + return http_errno_description(HTTP_PARSER_ERRNO(&request->parser)); } const char * http_request_get_method(http_request_t *request) { - assert(request); - return request->method; + assert(request); + return request->method; } const char * http_request_get_url(http_request_t *request) { - assert(request); - return request->url; + assert(request); + return request->url; } const char * http_request_get_header(http_request_t *request, const char *name) { - int i; + int i; - assert(request); + assert(request); - for (i=0; iheaders_size; i+=2) { - if (!strcmp(request->headers[i], name)) { - return request->headers[i+1]; - } - } - return NULL; + for (i=0; iheaders_size; i+=2) { + if (!strcmp(request->headers[i], name)) { + return request->headers[i+1]; + } + } + return NULL; } const char * http_request_get_data(http_request_t *request, int *datalen) { - assert(request); + assert(request); - if (datalen) { - *datalen = request->datalen; - } - return request->data; + if (datalen) { + *datalen = request->datalen; + } + return request->data; } diff --git a/lib/http_response.c b/lib/http_response.c index 41989756..91b30b80 100755 --- a/lib/http_response.c +++ b/lib/http_response.c @@ -21,145 +21,145 @@ #include "compat.h" struct http_response_s { - int complete; - int disconnect; + int complete; + int disconnect; - char *data; - int data_size; - int data_length; + char *data; + int data_size; + int data_length; }; static void http_response_add_data(http_response_t *response, const char *data, int datalen) { - int newdatasize; - - assert(response); - assert(data); - assert(datalen > 0); - - newdatasize = response->data_size; - while (response->data_size+datalen > newdatasize) { - newdatasize *= 2; - } - if (newdatasize != response->data_size) { - response->data = realloc(response->data, newdatasize); - assert(response->data); - } - memcpy(response->data+response->data_length, data, datalen); - response->data_length += datalen; + int newdatasize; + + assert(response); + assert(data); + assert(datalen > 0); + + newdatasize = response->data_size; + while (response->data_size+datalen > newdatasize) { + newdatasize *= 2; + } + if (newdatasize != response->data_size) { + response->data = realloc(response->data, newdatasize); + assert(response->data); + } + memcpy(response->data+response->data_length, data, datalen); + response->data_length += datalen; } http_response_t * http_response_init(const char *protocol, int code, const char *message) { - http_response_t *response; - char codestr[4]; - - assert(code >= 100 && code < 1000); - - /* Convert code into string */ - memset(codestr, 0, sizeof(codestr)); - snprintf(codestr, sizeof(codestr), "%u", code); - - response = calloc(1, sizeof(http_response_t)); - if (!response) { - return NULL; - } - - /* Allocate response data */ - response->data_size = 1024; - response->data = malloc(response->data_size); - if (!response->data) { - free(response); - return NULL; - } - - /* Add first line of response to the data array */ - http_response_add_data(response, protocol, strlen(protocol)); - http_response_add_data(response, " ", 1); - http_response_add_data(response, codestr, strlen(codestr)); - http_response_add_data(response, " ", 1); - http_response_add_data(response, message, strlen(message)); - http_response_add_data(response, "\r\n", 2); - - return response; + http_response_t *response; + char codestr[4]; + + assert(code >= 100 && code < 1000); + + /* Convert code into string */ + memset(codestr, 0, sizeof(codestr)); + snprintf(codestr, sizeof(codestr), "%u", code); + + response = calloc(1, sizeof(http_response_t)); + if (!response) { + return NULL; + } + + /* Allocate response data */ + response->data_size = 1024; + response->data = malloc(response->data_size); + if (!response->data) { + free(response); + return NULL; + } + + /* Add first line of response to the data array */ + http_response_add_data(response, protocol, strlen(protocol)); + http_response_add_data(response, " ", 1); + http_response_add_data(response, codestr, strlen(codestr)); + http_response_add_data(response, " ", 1); + http_response_add_data(response, message, strlen(message)); + http_response_add_data(response, "\r\n", 2); + + return response; } void http_response_destroy(http_response_t *response) { - if (response) { - free(response->data); - free(response); - } + if (response) { + free(response->data); + free(response); + } } void http_response_add_header(http_response_t *response, const char *name, const char *value) { - assert(response); - assert(name); - assert(value); - - http_response_add_data(response, name, strlen(name)); - http_response_add_data(response, ": ", 2); - http_response_add_data(response, value, strlen(value)); - http_response_add_data(response, "\r\n", 2); + assert(response); + assert(name); + assert(value); + + http_response_add_data(response, name, strlen(name)); + http_response_add_data(response, ": ", 2); + http_response_add_data(response, value, strlen(value)); + http_response_add_data(response, "\r\n", 2); } void http_response_finish(http_response_t *response, const char *data, int datalen) { - assert(response); - assert(datalen==0 || (data && datalen > 0)); - - if (data && datalen > 0) { - const char *hdrname = "Content-Length"; - char hdrvalue[16]; - - memset(hdrvalue, 0, sizeof(hdrvalue)); - snprintf(hdrvalue, sizeof(hdrvalue)-1, "%d", datalen); - - /* Add Content-Length header first */ - http_response_add_data(response, hdrname, strlen(hdrname)); - http_response_add_data(response, ": ", 2); - http_response_add_data(response, hdrvalue, strlen(hdrvalue)); - http_response_add_data(response, "\r\n\r\n", 4); - - /* Add data to the end of response */ - http_response_add_data(response, data, datalen); - } else { - /* Add extra end of line after headers */ - http_response_add_data(response, "\r\n", 2); - } - response->complete = 1; + assert(response); + assert(datalen==0 || (data && datalen > 0)); + + if (data && datalen > 0) { + const char *hdrname = "Content-Length"; + char hdrvalue[16]; + + memset(hdrvalue, 0, sizeof(hdrvalue)); + snprintf(hdrvalue, sizeof(hdrvalue)-1, "%d", datalen); + + /* Add Content-Length header first */ + http_response_add_data(response, hdrname, strlen(hdrname)); + http_response_add_data(response, ": ", 2); + http_response_add_data(response, hdrvalue, strlen(hdrvalue)); + http_response_add_data(response, "\r\n\r\n", 4); + + /* Add data to the end of response */ + http_response_add_data(response, data, datalen); + } else { + /* Add extra end of line after headers */ + http_response_add_data(response, "\r\n", 2); + } + response->complete = 1; } void http_response_set_disconnect(http_response_t *response, int disconnect) { - assert(response); + assert(response); - response->disconnect = !!disconnect; + response->disconnect = !!disconnect; } int http_response_get_disconnect(http_response_t *response) { - assert(response); + assert(response); - return response->disconnect; + return response->disconnect; } const char * http_response_get_data(http_response_t *response, int *datalen) { - assert(response); - assert(datalen); - assert(response->complete); + assert(response); + assert(datalen); + assert(response->complete); - *datalen = response->data_length; - return response->data; + *datalen = response->data_length; + return response->data; } diff --git a/lib/httpd.c b/lib/httpd.c index 491f9bc6..3aeee494 100755 --- a/lib/httpd.c +++ b/lib/httpd.c @@ -24,435 +24,435 @@ #include "logger.h" struct http_connection_s { - int connected; + int connected; - int socket_fd; - void *user_data; - http_request_t *request; + int socket_fd; + void *user_data; + http_request_t *request; }; typedef struct http_connection_s http_connection_t; struct httpd_s { - logger_t *logger; - httpd_callbacks_t callbacks; - - int max_connections; - int open_connections; - http_connection_t *connections; - - /* These variables only edited mutex locked */ - int running; - int joined; - thread_handle_t thread; - mutex_handle_t run_mutex; - - /* Server fds for accepting connections */ - int server_fd4; - int server_fd6; + logger_t *logger; + httpd_callbacks_t callbacks; + + int max_connections; + int open_connections; + http_connection_t *connections; + + /* These variables only edited mutex locked */ + int running; + int joined; + thread_handle_t thread; + mutex_handle_t run_mutex; + + /* Server fds for accepting connections */ + int server_fd4; + int server_fd6; }; httpd_t * httpd_init(logger_t *logger, httpd_callbacks_t *callbacks, int max_connections) { - httpd_t *httpd; + httpd_t *httpd; - assert(logger); - assert(callbacks); - assert(max_connections > 0); + assert(logger); + assert(callbacks); + assert(max_connections > 0); - /* Allocate the httpd_t structure */ - httpd = calloc(1, sizeof(httpd_t)); - if (!httpd) { - return NULL; - } + /* Allocate the httpd_t structure */ + httpd = calloc(1, sizeof(httpd_t)); + if (!httpd) { + return NULL; + } - httpd->max_connections = max_connections; - httpd->connections = calloc(max_connections, sizeof(http_connection_t)); - if (!httpd->connections) { - free(httpd); - return NULL; - } + httpd->max_connections = max_connections; + httpd->connections = calloc(max_connections, sizeof(http_connection_t)); + if (!httpd->connections) { + free(httpd); + return NULL; + } - /* Use the logger provided */ - httpd->logger = logger; + /* Use the logger provided */ + httpd->logger = logger; - /* Save callback pointers */ - memcpy(&httpd->callbacks, callbacks, sizeof(httpd_callbacks_t)); + /* Save callback pointers */ + memcpy(&httpd->callbacks, callbacks, sizeof(httpd_callbacks_t)); - /* Initial status joined */ - httpd->running = 0; - httpd->joined = 1; + /* Initial status joined */ + httpd->running = 0; + httpd->joined = 1; - return httpd; + return httpd; } void httpd_destroy(httpd_t *httpd) { - if (httpd) { - httpd_stop(httpd); + if (httpd) { + httpd_stop(httpd); - free(httpd->connections); - free(httpd); - } + free(httpd->connections); + free(httpd); + } } static int httpd_add_connection(httpd_t *httpd, int fd, unsigned char *local, int local_len, unsigned char *remote, int remote_len) { - void *user_data; - int i; - - for (i=0; imax_connections; i++) { - if (!httpd->connections[i].connected) { - break; - } - } - if (i == httpd->max_connections) { - /* This code should never be reached, we do not select server_fds when full */ - logger_log(httpd->logger, LOGGER_INFO, "Max connections reached"); - return -1; - } - - user_data = httpd->callbacks.conn_init(httpd->callbacks.opaque, local, local_len, remote, remote_len); - if (!user_data) { - logger_log(httpd->logger, LOGGER_ERR, "Error initializing HTTP request handler"); - return -1; - } - - httpd->open_connections++; - httpd->connections[i].socket_fd = fd; - httpd->connections[i].connected = 1; - httpd->connections[i].user_data = user_data; - return 0; + void *user_data; + int i; + + for (i=0; imax_connections; i++) { + if (!httpd->connections[i].connected) { + break; + } + } + if (i == httpd->max_connections) { + /* This code should never be reached, we do not select server_fds when full */ + logger_log(httpd->logger, LOGGER_INFO, "Max connections reached"); + return -1; + } + + user_data = httpd->callbacks.conn_init(httpd->callbacks.opaque, local, local_len, remote, remote_len); + if (!user_data) { + logger_log(httpd->logger, LOGGER_ERR, "Error initializing HTTP request handler"); + return -1; + } + + httpd->open_connections++; + httpd->connections[i].socket_fd = fd; + httpd->connections[i].connected = 1; + httpd->connections[i].user_data = user_data; + return 0; } static int httpd_accept_connection(httpd_t *httpd, int server_fd, int is_ipv6) { - struct sockaddr_storage remote_saddr; - socklen_t remote_saddrlen; - struct sockaddr_storage local_saddr; - socklen_t local_saddrlen; - unsigned char *local, *remote; - int local_len, remote_len; - int ret, fd; - - remote_saddrlen = sizeof(remote_saddr); - fd = accept(server_fd, (struct sockaddr *)&remote_saddr, &remote_saddrlen); - if (fd == -1) { - /* FIXME: Error happened */ - return -1; - } - - local_saddrlen = sizeof(local_saddr); - ret = getsockname(fd, (struct sockaddr *)&local_saddr, &local_saddrlen); - if (ret == -1) { - shutdown(fd, SHUT_RDWR); - closesocket(fd); - return 0; - } - - logger_log(httpd->logger, LOGGER_INFO, "Accepted %s client on socket %d", - (is_ipv6 ? "IPv6" : "IPv4"), fd); - local = netutils_get_address(&local_saddr, &local_len); - remote = netutils_get_address(&remote_saddr, &remote_len); - - ret = httpd_add_connection(httpd, fd, local, local_len, remote, remote_len); - if (ret == -1) { - shutdown(fd, SHUT_RDWR); - closesocket(fd); - return 0; - } - return 1; + struct sockaddr_storage remote_saddr; + socklen_t remote_saddrlen; + struct sockaddr_storage local_saddr; + socklen_t local_saddrlen; + unsigned char *local, *remote; + int local_len, remote_len; + int ret, fd; + + remote_saddrlen = sizeof(remote_saddr); + fd = accept(server_fd, (struct sockaddr *)&remote_saddr, &remote_saddrlen); + if (fd == -1) { + /* FIXME: Error happened */ + return -1; + } + + local_saddrlen = sizeof(local_saddr); + ret = getsockname(fd, (struct sockaddr *)&local_saddr, &local_saddrlen); + if (ret == -1) { + shutdown(fd, SHUT_RDWR); + closesocket(fd); + return 0; + } + + logger_log(httpd->logger, LOGGER_INFO, "Accepted %s client on socket %d", + (is_ipv6 ? "IPv6" : "IPv4"), fd); + local = netutils_get_address(&local_saddr, &local_len); + remote = netutils_get_address(&remote_saddr, &remote_len); + + ret = httpd_add_connection(httpd, fd, local, local_len, remote, remote_len); + if (ret == -1) { + shutdown(fd, SHUT_RDWR); + closesocket(fd); + return 0; + } + return 1; } static void httpd_remove_connection(httpd_t *httpd, http_connection_t *connection) { - if (connection->request) { - http_request_destroy(connection->request); - connection->request = NULL; - } - httpd->callbacks.conn_destroy(connection->user_data); - shutdown(connection->socket_fd, SHUT_WR); - closesocket(connection->socket_fd); - connection->connected = 0; - httpd->open_connections--; + if (connection->request) { + http_request_destroy(connection->request); + connection->request = NULL; + } + httpd->callbacks.conn_destroy(connection->user_data); + shutdown(connection->socket_fd, SHUT_WR); + closesocket(connection->socket_fd); + connection->connected = 0; + httpd->open_connections--; } static THREAD_RETVAL httpd_thread(void *arg) { - httpd_t *httpd = arg; - char buffer[1024]; - int i; - - assert(httpd); - - while (1) { - fd_set rfds; - struct timeval tv; - int nfds=0; - int ret; - - MUTEX_LOCK(httpd->run_mutex); - if (!httpd->running) { - MUTEX_UNLOCK(httpd->run_mutex); - break; - } - MUTEX_UNLOCK(httpd->run_mutex); - - /* Set timeout value to 5ms */ - tv.tv_sec = 1; - tv.tv_usec = 5000; - - /* Get the correct nfds value and set rfds */ - FD_ZERO(&rfds); - if (httpd->open_connections < httpd->max_connections) { - if (httpd->server_fd4 != -1) { - FD_SET(httpd->server_fd4, &rfds); - if (nfds <= httpd->server_fd4) { - nfds = httpd->server_fd4+1; - } - } - if (httpd->server_fd6 != -1) { - FD_SET(httpd->server_fd6, &rfds); - if (nfds <= httpd->server_fd6) { - nfds = httpd->server_fd6+1; - } - } - } - for (i=0; imax_connections; i++) { - int socket_fd; - if (!httpd->connections[i].connected) { - continue; - } - socket_fd = httpd->connections[i].socket_fd; - FD_SET(socket_fd, &rfds); - if (nfds <= socket_fd) { - nfds = socket_fd+1; - } - } - - ret = select(nfds, &rfds, NULL, NULL, &tv); - if (ret == 0) { - /* Timeout happened */ - continue; - } else if (ret == -1) { - logger_log(httpd->logger, LOGGER_ERR, "httpd error in select"); - break; - } - - if (httpd->open_connections < httpd->max_connections && - httpd->server_fd4 != -1 && FD_ISSET(httpd->server_fd4, &rfds)) { - ret = httpd_accept_connection(httpd, httpd->server_fd4, 0); - if (ret == -1) { + httpd_t *httpd = arg; + char buffer[1024]; + int i; + + assert(httpd); + + while (1) { + fd_set rfds; + struct timeval tv; + int nfds=0; + int ret; + + MUTEX_LOCK(httpd->run_mutex); + if (!httpd->running) { + MUTEX_UNLOCK(httpd->run_mutex); + break; + } + MUTEX_UNLOCK(httpd->run_mutex); + + /* Set timeout value to 5ms */ + tv.tv_sec = 1; + tv.tv_usec = 5000; + + /* Get the correct nfds value and set rfds */ + FD_ZERO(&rfds); + if (httpd->open_connections < httpd->max_connections) { + if (httpd->server_fd4 != -1) { + FD_SET(httpd->server_fd4, &rfds); + if (nfds <= httpd->server_fd4) { + nfds = httpd->server_fd4+1; + } + } + if (httpd->server_fd6 != -1) { + FD_SET(httpd->server_fd6, &rfds); + if (nfds <= httpd->server_fd6) { + nfds = httpd->server_fd6+1; + } + } + } + for (i=0; imax_connections; i++) { + int socket_fd; + if (!httpd->connections[i].connected) { + continue; + } + socket_fd = httpd->connections[i].socket_fd; + FD_SET(socket_fd, &rfds); + if (nfds <= socket_fd) { + nfds = socket_fd+1; + } + } + + ret = select(nfds, &rfds, NULL, NULL, &tv); + if (ret == 0) { + /* Timeout happened */ + continue; + } else if (ret == -1) { + logger_log(httpd->logger, LOGGER_ERR, "httpd error in select"); + break; + } + + if (httpd->open_connections < httpd->max_connections && + httpd->server_fd4 != -1 && FD_ISSET(httpd->server_fd4, &rfds)) { + ret = httpd_accept_connection(httpd, httpd->server_fd4, 0); + if (ret == -1) { logger_log(httpd->logger, LOGGER_ERR, "httpd error in accept ipv4"); break; - } else if (ret == 0) { - continue; - } - } - if (httpd->open_connections < httpd->max_connections && - httpd->server_fd6 != -1 && FD_ISSET(httpd->server_fd6, &rfds)) { - ret = httpd_accept_connection(httpd, httpd->server_fd6, 1); - if (ret == -1) { + } else if (ret == 0) { + continue; + } + } + if (httpd->open_connections < httpd->max_connections && + httpd->server_fd6 != -1 && FD_ISSET(httpd->server_fd6, &rfds)) { + ret = httpd_accept_connection(httpd, httpd->server_fd6, 1); + if (ret == -1) { logger_log(httpd->logger, LOGGER_ERR, "httpd error in accept ipv6"); - break; - } else if (ret == 0) { - continue; - } - } - for (i=0; imax_connections; i++) { - http_connection_t *connection = &httpd->connections[i]; - - if (!connection->connected) { - continue; - } - if (!FD_ISSET(connection->socket_fd, &rfds)) { - continue; - } - - /* If not in the middle of request, allocate one */ - if (!connection->request) { - connection->request = http_request_init(); - assert(connection->request); - } - - logger_log(httpd->logger, LOGGER_DEBUG, "httpd receiving on socket %d", connection->socket_fd); - ret = recv(connection->socket_fd, buffer, sizeof(buffer), 0); - if (ret == 0) { - logger_log(httpd->logger, LOGGER_INFO, "Connection closed for socket %d", connection->socket_fd); - httpd_remove_connection(httpd, connection); - continue; - } - - /* Parse HTTP request from data read from connection */ - http_request_add_data(connection->request, buffer, ret); - if (http_request_has_error(connection->request)) { - logger_log(httpd->logger, LOGGER_ERR, "httpd error in parsing: %s", http_request_get_error_name(connection->request)); - httpd_remove_connection(httpd, connection); - continue; - } - - /* If request is finished, process and deallocate */ - if (http_request_is_complete(connection->request)) { - http_response_t *response = NULL; - // Callback the received data to raop - httpd->callbacks.conn_request(connection->user_data, connection->request, &response); - http_request_destroy(connection->request); - connection->request = NULL; - - if (response) { - const char *data; - int datalen; - int written; - int ret; - - /* Get response data and datalen */ - data = http_response_get_data(response, &datalen); - - written = 0; - while (written < datalen) { - ret = send(connection->socket_fd, data+written, datalen-written, 0); - if (ret == -1) { - logger_log(httpd->logger, LOGGER_ERR, "httpd error in sending data"); - break; - } - written += ret; - } - - if (http_response_get_disconnect(response)) { - logger_log(httpd->logger, LOGGER_INFO, "Disconnecting on software request"); - httpd_remove_connection(httpd, connection); - } - } else { - logger_log(httpd->logger, LOGGER_WARNING, "httpd didn't get response"); - } - http_response_destroy(response); - } else { - logger_log(httpd->logger, LOGGER_DEBUG, "Request not complete, waiting for more data..."); - } - } - } - - /* Remove all connections that are still connected */ - for (i=0; imax_connections; i++) { - http_connection_t *connection = &httpd->connections[i]; - - if (!connection->connected) { - continue; - } - logger_log(httpd->logger, LOGGER_INFO, "Removing connection for socket %d", connection->socket_fd); - httpd_remove_connection(httpd, connection); - } - - /* Close server sockets since they are not used any more */ - if (httpd->server_fd4 != -1) { - shutdown(httpd->server_fd4, SHUT_RDWR); - closesocket(httpd->server_fd4); - httpd->server_fd4 = -1; - } - if (httpd->server_fd6 != -1) { - shutdown(httpd->server_fd6, SHUT_RDWR); - closesocket(httpd->server_fd6); - httpd->server_fd6 = -1; - } + break; + } else if (ret == 0) { + continue; + } + } + for (i=0; imax_connections; i++) { + http_connection_t *connection = &httpd->connections[i]; + + if (!connection->connected) { + continue; + } + if (!FD_ISSET(connection->socket_fd, &rfds)) { + continue; + } + + /* If not in the middle of request, allocate one */ + if (!connection->request) { + connection->request = http_request_init(); + assert(connection->request); + } + + logger_log(httpd->logger, LOGGER_DEBUG, "httpd receiving on socket %d", connection->socket_fd); + ret = recv(connection->socket_fd, buffer, sizeof(buffer), 0); + if (ret == 0) { + logger_log(httpd->logger, LOGGER_INFO, "Connection closed for socket %d", connection->socket_fd); + httpd_remove_connection(httpd, connection); + continue; + } + + /* Parse HTTP request from data read from connection */ + http_request_add_data(connection->request, buffer, ret); + if (http_request_has_error(connection->request)) { + logger_log(httpd->logger, LOGGER_ERR, "httpd error in parsing: %s", http_request_get_error_name(connection->request)); + httpd_remove_connection(httpd, connection); + continue; + } + + /* If request is finished, process and deallocate */ + if (http_request_is_complete(connection->request)) { + http_response_t *response = NULL; + // Callback the received data to raop + httpd->callbacks.conn_request(connection->user_data, connection->request, &response); + http_request_destroy(connection->request); + connection->request = NULL; + + if (response) { + const char *data; + int datalen; + int written; + int ret; + + /* Get response data and datalen */ + data = http_response_get_data(response, &datalen); + + written = 0; + while (written < datalen) { + ret = send(connection->socket_fd, data+written, datalen-written, 0); + if (ret == -1) { + logger_log(httpd->logger, LOGGER_ERR, "httpd error in sending data"); + break; + } + written += ret; + } + + if (http_response_get_disconnect(response)) { + logger_log(httpd->logger, LOGGER_INFO, "Disconnecting on software request"); + httpd_remove_connection(httpd, connection); + } + } else { + logger_log(httpd->logger, LOGGER_WARNING, "httpd didn't get response"); + } + http_response_destroy(response); + } else { + logger_log(httpd->logger, LOGGER_DEBUG, "Request not complete, waiting for more data..."); + } + } + } + + /* Remove all connections that are still connected */ + for (i=0; imax_connections; i++) { + http_connection_t *connection = &httpd->connections[i]; + + if (!connection->connected) { + continue; + } + logger_log(httpd->logger, LOGGER_INFO, "Removing connection for socket %d", connection->socket_fd); + httpd_remove_connection(httpd, connection); + } + + /* Close server sockets since they are not used any more */ + if (httpd->server_fd4 != -1) { + shutdown(httpd->server_fd4, SHUT_RDWR); + closesocket(httpd->server_fd4); + httpd->server_fd4 = -1; + } + if (httpd->server_fd6 != -1) { + shutdown(httpd->server_fd6, SHUT_RDWR); + closesocket(httpd->server_fd6); + httpd->server_fd6 = -1; + } // Ensure running reflects the actual state MUTEX_LOCK(httpd->run_mutex); httpd->running = 0; MUTEX_UNLOCK(httpd->run_mutex); - logger_log(httpd->logger, LOGGER_DEBUG, "Exiting HTTP thread"); + logger_log(httpd->logger, LOGGER_DEBUG, "Exiting HTTP thread"); - return 0; + return 0; } int httpd_start(httpd_t *httpd, unsigned short *port) { - /* How many connection attempts are kept in queue */ - int backlog = 5; - - assert(httpd); - assert(port); - - MUTEX_LOCK(httpd->run_mutex); - if (httpd->running || !httpd->joined) { - MUTEX_UNLOCK(httpd->run_mutex); - return 0; - } - - httpd->server_fd4 = netutils_init_socket(port, 0, 0); - if (httpd->server_fd4 == -1) { - logger_log(httpd->logger, LOGGER_ERR, "Error initialising socket %d", SOCKET_GET_ERROR()); - MUTEX_UNLOCK(httpd->run_mutex); - return -1; - } - httpd->server_fd6 = -1;/*= netutils_init_socket(port, 1, 0); + /* How many connection attempts are kept in queue */ + int backlog = 5; + + assert(httpd); + assert(port); + + MUTEX_LOCK(httpd->run_mutex); + if (httpd->running || !httpd->joined) { + MUTEX_UNLOCK(httpd->run_mutex); + return 0; + } + + httpd->server_fd4 = netutils_init_socket(port, 0, 0); + if (httpd->server_fd4 == -1) { + logger_log(httpd->logger, LOGGER_ERR, "Error initialising socket %d", SOCKET_GET_ERROR()); + MUTEX_UNLOCK(httpd->run_mutex); + return -1; + } + httpd->server_fd6 = -1;/*= netutils_init_socket(port, 1, 0); if (httpd->server_fd6 == -1) { logger_log(httpd->logger, LOGGER_WARNING, "Error initialising IPv6 socket %d", SOCKET_GET_ERROR()); logger_log(httpd->logger, LOGGER_WARNING, "Continuing without IPv6 support"); }*/ - if (httpd->server_fd4 != -1 && listen(httpd->server_fd4, backlog) == -1) { - logger_log(httpd->logger, LOGGER_ERR, "Error listening to IPv4 socket"); - closesocket(httpd->server_fd4); - closesocket(httpd->server_fd6); - MUTEX_UNLOCK(httpd->run_mutex); - return -2; - } - if (httpd->server_fd6 != -1 && listen(httpd->server_fd6, backlog) == -1) { - logger_log(httpd->logger, LOGGER_ERR, "Error listening to IPv6 socket"); - closesocket(httpd->server_fd4); - closesocket(httpd->server_fd6); - MUTEX_UNLOCK(httpd->run_mutex); - return -2; - } - logger_log(httpd->logger, LOGGER_INFO, "Initialized server socket(s)"); - - /* Set values correctly and create new thread */ - httpd->running = 1; - httpd->joined = 0; - THREAD_CREATE(httpd->thread, httpd_thread, httpd); - MUTEX_UNLOCK(httpd->run_mutex); - - return 1; + if (httpd->server_fd4 != -1 && listen(httpd->server_fd4, backlog) == -1) { + logger_log(httpd->logger, LOGGER_ERR, "Error listening to IPv4 socket"); + closesocket(httpd->server_fd4); + closesocket(httpd->server_fd6); + MUTEX_UNLOCK(httpd->run_mutex); + return -2; + } + if (httpd->server_fd6 != -1 && listen(httpd->server_fd6, backlog) == -1) { + logger_log(httpd->logger, LOGGER_ERR, "Error listening to IPv6 socket"); + closesocket(httpd->server_fd4); + closesocket(httpd->server_fd6); + MUTEX_UNLOCK(httpd->run_mutex); + return -2; + } + logger_log(httpd->logger, LOGGER_INFO, "Initialized server socket(s)"); + + /* Set values correctly and create new thread */ + httpd->running = 1; + httpd->joined = 0; + THREAD_CREATE(httpd->thread, httpd_thread, httpd); + MUTEX_UNLOCK(httpd->run_mutex); + + return 1; } int httpd_is_running(httpd_t *httpd) { - int running; + int running; - assert(httpd); + assert(httpd); - MUTEX_LOCK(httpd->run_mutex); - running = httpd->running || !httpd->joined; - MUTEX_UNLOCK(httpd->run_mutex); + MUTEX_LOCK(httpd->run_mutex); + running = httpd->running || !httpd->joined; + MUTEX_UNLOCK(httpd->run_mutex); - return running; + return running; } void httpd_stop(httpd_t *httpd) { - assert(httpd); + assert(httpd); - MUTEX_LOCK(httpd->run_mutex); - if (!httpd->running || httpd->joined) { - MUTEX_UNLOCK(httpd->run_mutex); - return; - } - httpd->running = 0; - MUTEX_UNLOCK(httpd->run_mutex); + MUTEX_LOCK(httpd->run_mutex); + if (!httpd->running || httpd->joined) { + MUTEX_UNLOCK(httpd->run_mutex); + return; + } + httpd->running = 0; + MUTEX_UNLOCK(httpd->run_mutex); - THREAD_JOIN(httpd->thread); + THREAD_JOIN(httpd->thread); - MUTEX_LOCK(httpd->run_mutex); - httpd->joined = 1; - MUTEX_UNLOCK(httpd->run_mutex); + MUTEX_LOCK(httpd->run_mutex); + httpd->joined = 1; + MUTEX_UNLOCK(httpd->run_mutex); } diff --git a/lib/memalign.h b/lib/memalign.h index 33aafb60..917e02a8 100755 --- a/lib/memalign.h +++ b/lib/memalign.h @@ -40,9 +40,9 @@ #define SYSTEM_GET_PAGESIZE(ret) ret = sysconf(_SC_PAGESIZE) #define SYSTEM_GET_TIME(ret) do {\ - struct timeval tv;\ - gettimeofday(&tv, NULL);\ - ret = (unsigned int)(tv.tv_sec*1000 + tv.tv_usec/1000);\ + struct timeval tv;\ + gettimeofday(&tv, NULL);\ + ret = (unsigned int)(tv.tv_sec*1000 + tv.tv_usec/1000);\ } while(0) #define ALIGNED_MALLOC(memptr, alignment, size) if (posix_memalign((void **)&memptr, alignment, size)) memptr = NULL diff --git a/lib/mirror_buffer.c b/lib/mirror_buffer.c index f8df5453..abb438ba 100755 --- a/lib/mirror_buffer.c +++ b/lib/mirror_buffer.c @@ -82,8 +82,8 @@ mirror_buffer_init_aes(mirror_buffer_t *mirror_buffer, uint64_t streamConnection mirror_buffer_t * mirror_buffer_init(logger_t *logger, - const unsigned char *aeskey, - const unsigned char *ecdh_secret) + const unsigned char *aeskey, + const unsigned char *ecdh_secret) { mirror_buffer_t *mirror_buffer; assert(aeskey); @@ -111,8 +111,8 @@ void mirror_buffer_decrypt(mirror_buffer_t *mirror_buffer, unsigned char* input, int encryptlen = ((inputLen - mirror_buffer->nextDecryptCount) / 16) * 16; // Aes decryption aes_ctr_start_fresh_block(mirror_buffer->aes_ctx); - aes_ctr_decrypt(mirror_buffer->aes_ctx, input + mirror_buffer->nextDecryptCount, - input + mirror_buffer->nextDecryptCount, encryptlen); + aes_ctr_decrypt(mirror_buffer->aes_ctx, input + mirror_buffer->nextDecryptCount, + input + mirror_buffer->nextDecryptCount, encryptlen); // Copy to output memcpy(output + mirror_buffer->nextDecryptCount, input + mirror_buffer->nextDecryptCount, encryptlen); int outputlength = mirror_buffer->nextDecryptCount + encryptlen; diff --git a/lib/netutils.c b/lib/netutils.c index adae86c9..9e160c7c 100755 --- a/lib/netutils.c +++ b/lib/netutils.c @@ -22,7 +22,7 @@ int netutils_init() { #ifdef WIN32 - WORD wVersionRequested; + WORD wVersionRequested; WSADATA wsaData; int ret; @@ -38,166 +38,166 @@ netutils_init() return -1; } #endif - return 0; + return 0; } void netutils_cleanup() { #ifdef WIN32 - WSACleanup(); + WSACleanup(); #endif } unsigned char * netutils_get_address(void *sockaddr, int *length) { - unsigned char ipv4_prefix[] = { 0,0,0,0,0,0,0,0,0,0,255,255 }; - struct sockaddr *address = sockaddr; - - assert(address); - assert(length); - - if (address->sa_family == AF_INET) { - struct sockaddr_in *sin; - - sin = (struct sockaddr_in *)address; - *length = sizeof(sin->sin_addr.s_addr); - return (unsigned char *)&sin->sin_addr.s_addr; - } else if (address->sa_family == AF_INET6) { - struct sockaddr_in6 *sin6; - - sin6 = (struct sockaddr_in6 *)address; - if (!memcmp(sin6->sin6_addr.s6_addr, ipv4_prefix, 12)) { - /* Actually an embedded IPv4 address */ - *length = sizeof(sin6->sin6_addr.s6_addr)-12; - return (sin6->sin6_addr.s6_addr+12); - } - *length = sizeof(sin6->sin6_addr.s6_addr); - return sin6->sin6_addr.s6_addr; - } - - *length = 0; - return NULL; + unsigned char ipv4_prefix[] = { 0,0,0,0,0,0,0,0,0,0,255,255 }; + struct sockaddr *address = sockaddr; + + assert(address); + assert(length); + + if (address->sa_family == AF_INET) { + struct sockaddr_in *sin; + + sin = (struct sockaddr_in *)address; + *length = sizeof(sin->sin_addr.s_addr); + return (unsigned char *)&sin->sin_addr.s_addr; + } else if (address->sa_family == AF_INET6) { + struct sockaddr_in6 *sin6; + + sin6 = (struct sockaddr_in6 *)address; + if (!memcmp(sin6->sin6_addr.s6_addr, ipv4_prefix, 12)) { + /* Actually an embedded IPv4 address */ + *length = sizeof(sin6->sin6_addr.s6_addr)-12; + return (sin6->sin6_addr.s6_addr+12); + } + *length = sizeof(sin6->sin6_addr.s6_addr); + return sin6->sin6_addr.s6_addr; + } + + *length = 0; + return NULL; } int netutils_init_socket(unsigned short *port, int use_ipv6, int use_udp) { - int family = use_ipv6 ? AF_INET6 : AF_INET; - int type = use_udp ? SOCK_DGRAM : SOCK_STREAM; - int proto = use_udp ? IPPROTO_UDP : IPPROTO_TCP; - - struct sockaddr_storage saddr; - socklen_t socklen; - int server_fd; - int ret; - int reuseaddr = 1; - - assert(port); - - server_fd = socket(family, type, proto); - if (server_fd == -1) { - goto cleanup; - } - - ret = setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof (reuseaddr)); - if (ret == -1) { - goto cleanup; - } - - memset(&saddr, 0, sizeof(saddr)); - if (use_ipv6) { - struct sockaddr_in6 *sin6ptr = (struct sockaddr_in6 *)&saddr; - int v6only = 1; - - /* Initialize sockaddr for bind */ - sin6ptr->sin6_family = family; - sin6ptr->sin6_addr = in6addr_any; - sin6ptr->sin6_port = htons(*port); + int family = use_ipv6 ? AF_INET6 : AF_INET; + int type = use_udp ? SOCK_DGRAM : SOCK_STREAM; + int proto = use_udp ? IPPROTO_UDP : IPPROTO_TCP; + + struct sockaddr_storage saddr; + socklen_t socklen; + int server_fd; + int ret; + int reuseaddr = 1; + + assert(port); + + server_fd = socket(family, type, proto); + if (server_fd == -1) { + goto cleanup; + } + + ret = setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof (reuseaddr)); + if (ret == -1) { + goto cleanup; + } + + memset(&saddr, 0, sizeof(saddr)); + if (use_ipv6) { + struct sockaddr_in6 *sin6ptr = (struct sockaddr_in6 *)&saddr; + int v6only = 1; + + /* Initialize sockaddr for bind */ + sin6ptr->sin6_family = family; + sin6ptr->sin6_addr = in6addr_any; + sin6ptr->sin6_port = htons(*port); #ifndef WIN32 - /* Make sure we only listen to IPv6 addresses */ - setsockopt(server_fd, IPPROTO_IPV6, IPV6_V6ONLY, - (char *) &v6only, sizeof(v6only)); + /* Make sure we only listen to IPv6 addresses */ + setsockopt(server_fd, IPPROTO_IPV6, IPV6_V6ONLY, + (char *) &v6only, sizeof(v6only)); #endif - socklen = sizeof(*sin6ptr); - ret = bind(server_fd, (struct sockaddr *)sin6ptr, socklen); - if (ret == -1) { - goto cleanup; - } - - ret = getsockname(server_fd, (struct sockaddr *)sin6ptr, &socklen); - if (ret == -1) { - goto cleanup; - } - *port = ntohs(sin6ptr->sin6_port); - } else { - struct sockaddr_in *sinptr = (struct sockaddr_in *)&saddr; - - /* Initialize sockaddr for bind */ - sinptr->sin_family = family; - sinptr->sin_addr.s_addr = INADDR_ANY; - sinptr->sin_port = htons(*port); - - socklen = sizeof(*sinptr); - ret = bind(server_fd, (struct sockaddr *)sinptr, socklen); - if (ret == -1) { - goto cleanup; - } - - ret = getsockname(server_fd, (struct sockaddr *)sinptr, &socklen); - if (ret == -1) { - goto cleanup; - } - *port = ntohs(sinptr->sin_port); - } - return server_fd; - - cleanup: - ret = SOCKET_GET_ERROR(); - if (server_fd != -1) { - closesocket(server_fd); - } - SOCKET_SET_ERROR(ret); - return -1; + socklen = sizeof(*sin6ptr); + ret = bind(server_fd, (struct sockaddr *)sin6ptr, socklen); + if (ret == -1) { + goto cleanup; + } + + ret = getsockname(server_fd, (struct sockaddr *)sin6ptr, &socklen); + if (ret == -1) { + goto cleanup; + } + *port = ntohs(sin6ptr->sin6_port); + } else { + struct sockaddr_in *sinptr = (struct sockaddr_in *)&saddr; + + /* Initialize sockaddr for bind */ + sinptr->sin_family = family; + sinptr->sin_addr.s_addr = INADDR_ANY; + sinptr->sin_port = htons(*port); + + socklen = sizeof(*sinptr); + ret = bind(server_fd, (struct sockaddr *)sinptr, socklen); + if (ret == -1) { + goto cleanup; + } + + ret = getsockname(server_fd, (struct sockaddr *)sinptr, &socklen); + if (ret == -1) { + goto cleanup; + } + *port = ntohs(sinptr->sin_port); + } + return server_fd; + + cleanup: + ret = SOCKET_GET_ERROR(); + if (server_fd != -1) { + closesocket(server_fd); + } + SOCKET_SET_ERROR(ret); + return -1; } // Src is the ip address int netutils_parse_address(int family, const char *src, void *dst, int dstlen) { - struct addrinfo *result; - struct addrinfo *ptr; - struct addrinfo hints; - int length; - int ret; - - if (family != AF_INET && family != AF_INET6) { - return -1; - } - if (!src || !dst) { - return -1; - } - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = family; - hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; - - ret = getaddrinfo(src, NULL, &hints, &result); - if (ret != 0) { - return -1; - } - - length = -1; - for (ptr=result; ptr!=NULL; ptr=ptr->ai_next) { - if (family == ptr->ai_family && (unsigned int)dstlen >= ptr->ai_addrlen) { - memcpy(dst, ptr->ai_addr, ptr->ai_addrlen); - length = ptr->ai_addrlen; - break; - } - } - freeaddrinfo(result); - return length; + struct addrinfo *result; + struct addrinfo *ptr; + struct addrinfo hints; + int length; + int ret; + + if (family != AF_INET && family != AF_INET6) { + return -1; + } + if (!src || !dst) { + return -1; + } + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = family; + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; + + ret = getaddrinfo(src, NULL, &hints, &result); + if (ret != 0) { + return -1; + } + + length = -1; + for (ptr=result; ptr!=NULL; ptr=ptr->ai_next) { + if (family == ptr->ai_family && (unsigned int)dstlen >= ptr->ai_addrlen) { + memcpy(dst, ptr->ai_addr, ptr->ai_addrlen); + length = ptr->ai_addrlen; + break; + } + } + freeaddrinfo(result); + return length; } diff --git a/lib/pairing.c b/lib/pairing.c index 344d1001..1a70cc54 100755 --- a/lib/pairing.c +++ b/lib/pairing.c @@ -25,107 +25,107 @@ #define SALT_IV "Pair-Verify-AES-IV" struct pairing_s { - unsigned char ed_private[64]; - unsigned char ed_public[32]; + unsigned char ed_private[64]; + unsigned char ed_public[32]; }; typedef enum { - STATUS_INITIAL, + STATUS_INITIAL, STATUS_SETUP, - STATUS_HANDSHAKE, - STATUS_FINISHED + STATUS_HANDSHAKE, + STATUS_FINISHED } status_t; struct pairing_session_s { - status_t status; + status_t status; - unsigned char ed_private[64]; - unsigned char ed_ours[32]; - unsigned char ed_theirs[32]; + unsigned char ed_private[64]; + unsigned char ed_ours[32]; + unsigned char ed_theirs[32]; - unsigned char ecdh_ours[32]; - unsigned char ecdh_theirs[32]; - unsigned char ecdh_secret[32]; + unsigned char ecdh_ours[32]; + unsigned char ecdh_theirs[32]; + unsigned char ecdh_secret[32]; }; static int derive_key_internal(pairing_session_t *session, const unsigned char *salt, unsigned int saltlen, unsigned char *key, unsigned int keylen) { - unsigned char hash[64]; + unsigned char hash[64]; - if (keylen > sizeof(hash)) { - return -1; - } + if (keylen > sizeof(hash)) { + return -1; + } sha_ctx_t *ctx = sha_init(); - sha_update(ctx, salt, saltlen); - sha_update(ctx, session->ecdh_secret, 32); - sha_final(ctx, hash, NULL); - sha_destroy(ctx); + sha_update(ctx, salt, saltlen); + sha_update(ctx, session->ecdh_secret, 32); + sha_final(ctx, hash, NULL); + sha_destroy(ctx); - memcpy(key, hash, keylen); - return 0; + memcpy(key, hash, keylen); + return 0; } pairing_t * pairing_init_generate() { - unsigned char seed[32]; + unsigned char seed[32]; - if (ed25519_create_seed(seed)) { - return NULL; - } - return pairing_init_seed(seed); + if (ed25519_create_seed(seed)) { + return NULL; + } + return pairing_init_seed(seed); } pairing_t * pairing_init_seed(const unsigned char seed[32]) { - pairing_t *pairing; + pairing_t *pairing; - pairing = calloc(1, sizeof(pairing_t)); - if (!pairing) { - return NULL; - } + pairing = calloc(1, sizeof(pairing_t)); + if (!pairing) { + return NULL; + } - ed25519_create_keypair(pairing->ed_public, pairing->ed_private, seed); - return pairing; + ed25519_create_keypair(pairing->ed_public, pairing->ed_private, seed); + return pairing; } void pairing_get_public_key(pairing_t *pairing, unsigned char public_key[32]) { - assert(pairing); + assert(pairing); - memcpy(public_key, pairing->ed_public, 32); + memcpy(public_key, pairing->ed_public, 32); } void pairing_get_ecdh_secret_key(pairing_session_t *session, unsigned char ecdh_secret[32]) { - assert(session); - memcpy(ecdh_secret, session->ecdh_secret, 32); + assert(session); + memcpy(ecdh_secret, session->ecdh_secret, 32); } pairing_session_t * pairing_session_init(pairing_t *pairing) { - pairing_session_t *session; + pairing_session_t *session; - if (!pairing) { - return NULL; - } + if (!pairing) { + return NULL; + } - session = calloc(1, sizeof(pairing_session_t)); - if (!session) { - return NULL; - } - memcpy(session->ed_private, pairing->ed_private, 64); - memcpy(session->ed_ours, pairing->ed_public, 32); - session->status = STATUS_INITIAL; + session = calloc(1, sizeof(pairing_session_t)); + if (!session) { + return NULL; + } + memcpy(session->ed_private, pairing->ed_private, 64); + memcpy(session->ed_ours, pairing->ed_public, 32); + session->status = STATUS_INITIAL; - return session; + return session; } void @@ -148,114 +148,114 @@ pairing_session_check_handshake_status(pairing_session_t *session) int pairing_session_handshake(pairing_session_t *session, const unsigned char ecdh_key[32], const unsigned char ed_key[32]) { - unsigned char ecdh_priv[32]; + unsigned char ecdh_priv[32]; - assert(session); + assert(session); - if (session->status == STATUS_FINISHED) { - return -1; - } - if (ed25519_create_seed(ecdh_priv)) { - return -2; - } + if (session->status == STATUS_FINISHED) { + return -1; + } + if (ed25519_create_seed(ecdh_priv)) { + return -2; + } - memcpy(session->ecdh_theirs, ecdh_key, 32); - memcpy(session->ed_theirs, ed_key, 32); - curve25519_donna(session->ecdh_ours, ecdh_priv, kCurve25519BasePoint); - curve25519_donna(session->ecdh_secret, ecdh_priv, session->ecdh_theirs); + memcpy(session->ecdh_theirs, ecdh_key, 32); + memcpy(session->ed_theirs, ed_key, 32); + curve25519_donna(session->ecdh_ours, ecdh_priv, kCurve25519BasePoint); + curve25519_donna(session->ecdh_secret, ecdh_priv, session->ecdh_theirs); - session->status = STATUS_HANDSHAKE; - return 0; + session->status = STATUS_HANDSHAKE; + return 0; } int pairing_session_get_public_key(pairing_session_t *session, unsigned char ecdh_key[32]) { - assert(session); + assert(session); - if (session->status != STATUS_HANDSHAKE) { - return -1; - } + if (session->status != STATUS_HANDSHAKE) { + return -1; + } - memcpy(ecdh_key, session->ecdh_ours, 32); - return 0; + memcpy(ecdh_key, session->ecdh_ours, 32); + return 0; } int pairing_session_get_signature(pairing_session_t *session, unsigned char signature[64]) { - unsigned char sig_msg[64]; - unsigned char key[16]; - unsigned char iv[16]; - aes_ctx_t *aes_ctx; + unsigned char sig_msg[64]; + unsigned char key[16]; + unsigned char iv[16]; + aes_ctx_t *aes_ctx; + + assert(session); - assert(session); + if (session->status != STATUS_HANDSHAKE) { + return -1; + } - if (session->status != STATUS_HANDSHAKE) { - return -1; - } + /* First sign the public ECDH keys of both parties */ + memcpy(&sig_msg[0], session->ecdh_ours, 32); + memcpy(&sig_msg[32], session->ecdh_theirs, 32); - /* First sign the public ECDH keys of both parties */ - memcpy(&sig_msg[0], session->ecdh_ours, 32); - memcpy(&sig_msg[32], session->ecdh_theirs, 32); + ed25519_sign(signature, sig_msg, sizeof(sig_msg), session->ed_ours, session->ed_private); - ed25519_sign(signature, sig_msg, sizeof(sig_msg), session->ed_ours, session->ed_private); + /* Then encrypt the result with keys derived from the shared secret */ + derive_key_internal(session, (const unsigned char *) SALT_KEY, strlen(SALT_KEY), key, sizeof(key)); + derive_key_internal(session, (const unsigned char *) SALT_IV, strlen(SALT_IV), iv, sizeof(key)); - /* Then encrypt the result with keys derived from the shared secret */ - derive_key_internal(session, (const unsigned char *) SALT_KEY, strlen(SALT_KEY), key, sizeof(key)); - derive_key_internal(session, (const unsigned char *) SALT_IV, strlen(SALT_IV), iv, sizeof(key)); - - aes_ctx = aes_ctr_init(key, iv); - aes_ctr_encrypt(aes_ctx, signature, signature, 64); - aes_ctr_destroy(aes_ctx); + aes_ctx = aes_ctr_init(key, iv); + aes_ctr_encrypt(aes_ctx, signature, signature, 64); + aes_ctr_destroy(aes_ctx); - return 0; + return 0; } int pairing_session_finish(pairing_session_t *session, const unsigned char signature[64]) { - unsigned char sig_buffer[64]; - unsigned char sig_msg[64]; - unsigned char key[16]; - unsigned char iv[16]; - aes_ctx_t *aes_ctx; - - assert(session); - - if (session->status != STATUS_HANDSHAKE) { - return -1; - } - - /* First decrypt the signature with keys derived from the shared secret */ - derive_key_internal(session, (const unsigned char *) SALT_KEY, strlen(SALT_KEY), key, sizeof(key)); - derive_key_internal(session, (const unsigned char *) SALT_IV, strlen(SALT_IV), iv, sizeof(key)); - - aes_ctx = aes_ctr_init(key, iv); - /* One fake round for the initial handshake encryption */ - aes_ctr_encrypt(aes_ctx, sig_buffer, sig_buffer, 64); - aes_ctr_encrypt(aes_ctx, signature, sig_buffer, 64); - aes_ctr_destroy(aes_ctx); - - /* Then verify the signature with public ECDH keys of both parties */ - memcpy(&sig_msg[0], session->ecdh_theirs, 32); - memcpy(&sig_msg[32], session->ecdh_ours, 32); - if (!ed25519_verify(sig_buffer, sig_msg, sizeof(sig_msg), session->ed_theirs)) { - return -2; - } - - session->status = STATUS_FINISHED; - return 0; + unsigned char sig_buffer[64]; + unsigned char sig_msg[64]; + unsigned char key[16]; + unsigned char iv[16]; + aes_ctx_t *aes_ctx; + + assert(session); + + if (session->status != STATUS_HANDSHAKE) { + return -1; + } + + /* First decrypt the signature with keys derived from the shared secret */ + derive_key_internal(session, (const unsigned char *) SALT_KEY, strlen(SALT_KEY), key, sizeof(key)); + derive_key_internal(session, (const unsigned char *) SALT_IV, strlen(SALT_IV), iv, sizeof(key)); + + aes_ctx = aes_ctr_init(key, iv); + /* One fake round for the initial handshake encryption */ + aes_ctr_encrypt(aes_ctx, sig_buffer, sig_buffer, 64); + aes_ctr_encrypt(aes_ctx, signature, sig_buffer, 64); + aes_ctr_destroy(aes_ctx); + + /* Then verify the signature with public ECDH keys of both parties */ + memcpy(&sig_msg[0], session->ecdh_theirs, 32); + memcpy(&sig_msg[32], session->ecdh_ours, 32); + if (!ed25519_verify(sig_buffer, sig_msg, sizeof(sig_msg), session->ed_theirs)) { + return -2; + } + + session->status = STATUS_FINISHED; + return 0; } void pairing_session_destroy(pairing_session_t *session) { - free(session); + free(session); } void pairing_destroy(pairing_t *pairing) { - free(pairing); + free(pairing); } diff --git a/lib/raop.c b/lib/raop.c index 9a2bde18..7eca21f4 100755 --- a/lib/raop.c +++ b/lib/raop.c @@ -32,34 +32,34 @@ #include "raop_ntp.h" struct raop_s { - /* Callbacks for audio and video */ - raop_callbacks_t callbacks; + /* Callbacks for audio and video */ + raop_callbacks_t callbacks; - /* Logger instance */ - logger_t *logger; + /* Logger instance */ + logger_t *logger; - /* Pairing, HTTP daemon and RSA key */ - pairing_t *pairing; - httpd_t *httpd; + /* Pairing, HTTP daemon and RSA key */ + pairing_t *pairing; + httpd_t *httpd; - dnssd_t *dnssd; + dnssd_t *dnssd; unsigned short port; }; struct raop_conn_s { - raop_t *raop; - raop_ntp_t *raop_ntp; - raop_rtp_t *raop_rtp; - raop_rtp_mirror_t *raop_rtp_mirror; - fairplay_t *fairplay; - pairing_session_t *pairing; + raop_t *raop; + raop_ntp_t *raop_ntp; + raop_rtp_t *raop_rtp; + raop_rtp_mirror_t *raop_rtp_mirror; + fairplay_t *fairplay; + pairing_session_t *pairing; - unsigned char *local; - int locallen; + unsigned char *local; + int locallen; - unsigned char *remote; - int remotelen; + unsigned char *remote; + int remotelen; }; typedef struct raop_conn_s raop_conn_t; @@ -69,167 +69,167 @@ typedef struct raop_conn_s raop_conn_t; static void * conn_init(void *opaque, unsigned char *local, int locallen, unsigned char *remote, int remotelen) { - raop_t *raop = opaque; - raop_conn_t *conn; + raop_t *raop = opaque; + raop_conn_t *conn; - assert(raop); + assert(raop); - conn = calloc(1, sizeof(raop_conn_t)); - if (!conn) { - return NULL; - } - conn->raop = raop; - conn->raop_rtp = NULL; + conn = calloc(1, sizeof(raop_conn_t)); + if (!conn) { + return NULL; + } + conn->raop = raop; + conn->raop_rtp = NULL; conn->raop_ntp = NULL; conn->fairplay = fairplay_init(raop->logger); - if (!conn->fairplay) { - free(conn); - return NULL; - } - conn->pairing = pairing_session_init(raop->pairing); - if (!conn->pairing) { - fairplay_destroy(conn->fairplay); - free(conn); - return NULL; - } - - if (locallen == 4) { - logger_log(conn->raop->logger, LOGGER_INFO, - "Local: %d.%d.%d.%d", - local[0], local[1], local[2], local[3]); - } else if (locallen == 16) { - logger_log(conn->raop->logger, LOGGER_INFO, - "Local: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", - local[0], local[1], local[2], local[3], local[4], local[5], local[6], local[7], - local[8], local[9], local[10], local[11], local[12], local[13], local[14], local[15]); - } - if (remotelen == 4) { - logger_log(conn->raop->logger, LOGGER_INFO, - "Remote: %d.%d.%d.%d", - remote[0], remote[1], remote[2], remote[3]); - } else if (remotelen == 16) { - logger_log(conn->raop->logger, LOGGER_INFO, - "Remote: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", - remote[0], remote[1], remote[2], remote[3], remote[4], remote[5], remote[6], remote[7], - remote[8], remote[9], remote[10], remote[11], remote[12], remote[13], remote[14], remote[15]); - } - - conn->local = malloc(locallen); - assert(conn->local); - memcpy(conn->local, local, locallen); - - conn->remote = malloc(remotelen); - assert(conn->remote); - memcpy(conn->remote, remote, remotelen); - - conn->locallen = locallen; - conn->remotelen = remotelen; - - return conn; + if (!conn->fairplay) { + free(conn); + return NULL; + } + conn->pairing = pairing_session_init(raop->pairing); + if (!conn->pairing) { + fairplay_destroy(conn->fairplay); + free(conn); + return NULL; + } + + if (locallen == 4) { + logger_log(conn->raop->logger, LOGGER_INFO, + "Local: %d.%d.%d.%d", + local[0], local[1], local[2], local[3]); + } else if (locallen == 16) { + logger_log(conn->raop->logger, LOGGER_INFO, + "Local: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", + local[0], local[1], local[2], local[3], local[4], local[5], local[6], local[7], + local[8], local[9], local[10], local[11], local[12], local[13], local[14], local[15]); + } + if (remotelen == 4) { + logger_log(conn->raop->logger, LOGGER_INFO, + "Remote: %d.%d.%d.%d", + remote[0], remote[1], remote[2], remote[3]); + } else if (remotelen == 16) { + logger_log(conn->raop->logger, LOGGER_INFO, + "Remote: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", + remote[0], remote[1], remote[2], remote[3], remote[4], remote[5], remote[6], remote[7], + remote[8], remote[9], remote[10], remote[11], remote[12], remote[13], remote[14], remote[15]); + } + + conn->local = malloc(locallen); + assert(conn->local); + memcpy(conn->local, local, locallen); + + conn->remote = malloc(remotelen); + assert(conn->remote); + memcpy(conn->remote, remote, remotelen); + + conn->locallen = locallen; + conn->remotelen = remotelen; + + return conn; } static void conn_request(void *ptr, http_request_t *request, http_response_t **response) { - raop_conn_t *conn = ptr; + raop_conn_t *conn = ptr; logger_log(conn->raop->logger, LOGGER_DEBUG, "conn_request"); - const char *method; - const char *url; - const char *cseq; - - char *response_data = NULL; - int response_datalen = 0; - - method = http_request_get_method(request); - url = http_request_get_url(request); - cseq = http_request_get_header(request, "CSeq"); - if (!method || !cseq) { - return; - } - - *response = http_response_init("RTSP/1.0", 200, "OK"); - - http_response_add_header(*response, "CSeq", cseq); - //http_response_add_header(*response, "Apple-Jack-Status", "connected; type=analog"); - http_response_add_header(*response, "Server", "AirTunes/220.68"); - - logger_log(conn->raop->logger, LOGGER_DEBUG, "Handling request %s with URL %s", method, url); - raop_handler_t handler = NULL; - if (!strcmp(method, "GET") && !strcmp(url, "/info")) { - handler = &raop_handler_info; - } else if (!strcmp(method, "POST") && !strcmp(url, "/pair-setup")) { - handler = &raop_handler_pairsetup; - } else if (!strcmp(method, "POST") && !strcmp(url, "/pair-verify")) { - handler = &raop_handler_pairverify; - } else if (!strcmp(method, "POST") && !strcmp(url, "/fp-setup")) { - handler = &raop_handler_fpsetup; - } else if (!strcmp(method, "OPTIONS")) { - handler = &raop_handler_options; - } else if (!strcmp(method, "SETUP")) { - handler = &raop_handler_setup; - } else if (!strcmp(method, "GET_PARAMETER")) { - handler = &raop_handler_get_parameter; - } else if (!strcmp(method, "SET_PARAMETER")) { - handler = &raop_handler_set_parameter; - } else if (!strcmp(method, "POST") && !strcmp(url, "/feedback")) { - handler = &raop_handler_feedback; - } else if (!strcmp(method, "RECORD")) { + const char *method; + const char *url; + const char *cseq; + + char *response_data = NULL; + int response_datalen = 0; + + method = http_request_get_method(request); + url = http_request_get_url(request); + cseq = http_request_get_header(request, "CSeq"); + if (!method || !cseq) { + return; + } + + *response = http_response_init("RTSP/1.0", 200, "OK"); + + http_response_add_header(*response, "CSeq", cseq); + //http_response_add_header(*response, "Apple-Jack-Status", "connected; type=analog"); + http_response_add_header(*response, "Server", "AirTunes/220.68"); + + logger_log(conn->raop->logger, LOGGER_DEBUG, "Handling request %s with URL %s", method, url); + raop_handler_t handler = NULL; + if (!strcmp(method, "GET") && !strcmp(url, "/info")) { + handler = &raop_handler_info; + } else if (!strcmp(method, "POST") && !strcmp(url, "/pair-setup")) { + handler = &raop_handler_pairsetup; + } else if (!strcmp(method, "POST") && !strcmp(url, "/pair-verify")) { + handler = &raop_handler_pairverify; + } else if (!strcmp(method, "POST") && !strcmp(url, "/fp-setup")) { + handler = &raop_handler_fpsetup; + } else if (!strcmp(method, "OPTIONS")) { + handler = &raop_handler_options; + } else if (!strcmp(method, "SETUP")) { + handler = &raop_handler_setup; + } else if (!strcmp(method, "GET_PARAMETER")) { + handler = &raop_handler_get_parameter; + } else if (!strcmp(method, "SET_PARAMETER")) { + handler = &raop_handler_set_parameter; + } else if (!strcmp(method, "POST") && !strcmp(url, "/feedback")) { + handler = &raop_handler_feedback; + } else if (!strcmp(method, "RECORD")) { handler = &raop_handler_record; - } else if (!strcmp(method, "FLUSH")) { - const char *rtpinfo; - int next_seq = -1; - - rtpinfo = http_request_get_header(request, "RTP-Info"); - if (rtpinfo) { - logger_log(conn->raop->logger, LOGGER_DEBUG, "Flush with RTP-Info: %s", rtpinfo); - if (!strncmp(rtpinfo, "seq=", 4)) { - next_seq = strtol(rtpinfo+4, NULL, 10); - } - } - if (conn->raop_rtp) { - raop_rtp_flush(conn->raop_rtp, next_seq); - } else { - logger_log(conn->raop->logger, LOGGER_WARNING, "RAOP not initialized at FLUSH"); - } - } else if (!strcmp(method, "TEARDOWN")) { - //http_response_add_header(*response, "Connection", "close"); - if (conn->raop_rtp != NULL && raop_rtp_is_running(conn->raop_rtp)) { - /* Destroy our RTP session */ - raop_rtp_stop(conn->raop_rtp); - } else if (conn->raop_rtp_mirror) { + } else if (!strcmp(method, "FLUSH")) { + const char *rtpinfo; + int next_seq = -1; + + rtpinfo = http_request_get_header(request, "RTP-Info"); + if (rtpinfo) { + logger_log(conn->raop->logger, LOGGER_DEBUG, "Flush with RTP-Info: %s", rtpinfo); + if (!strncmp(rtpinfo, "seq=", 4)) { + next_seq = strtol(rtpinfo+4, NULL, 10); + } + } + if (conn->raop_rtp) { + raop_rtp_flush(conn->raop_rtp, next_seq); + } else { + logger_log(conn->raop->logger, LOGGER_WARNING, "RAOP not initialized at FLUSH"); + } + } else if (!strcmp(method, "TEARDOWN")) { + //http_response_add_header(*response, "Connection", "close"); + if (conn->raop_rtp != NULL && raop_rtp_is_running(conn->raop_rtp)) { + /* Destroy our RTP session */ + raop_rtp_stop(conn->raop_rtp); + } else if (conn->raop_rtp_mirror) { /* Destroy our sessions */ raop_rtp_destroy(conn->raop_rtp); conn->raop_rtp = NULL; raop_rtp_mirror_destroy(conn->raop_rtp_mirror); conn->raop_rtp_mirror = NULL; } - } - if (handler != NULL) { - handler(conn, request, *response, &response_data, &response_datalen); - } - http_response_finish(*response, response_data, response_datalen); - if (response_data) { - free(response_data); - response_data = NULL; - response_datalen = 0; - } + } + if (handler != NULL) { + handler(conn, request, *response, &response_data, &response_datalen); + } + http_response_finish(*response, response_data, response_datalen); + if (response_data) { + free(response_data); + response_data = NULL; + response_datalen = 0; + } } static void conn_destroy(void *ptr) { - raop_conn_t *conn = ptr; + raop_conn_t *conn = ptr; logger_log(conn->raop->logger, LOGGER_INFO, "Destroying connection"); if (conn->raop_ntp) { - raop_ntp_destroy(conn->raop_ntp); - } - if (conn->raop_rtp) { - /* This is done in case TEARDOWN was not called */ - raop_rtp_destroy(conn->raop_rtp); - } + raop_ntp_destroy(conn->raop_ntp); + } + if (conn->raop_rtp) { + /* This is done in case TEARDOWN was not called */ + raop_rtp_destroy(conn->raop_rtp); + } if (conn->raop_rtp_mirror) { /* This is done in case TEARDOWN was not called */ raop_rtp_mirror_destroy(conn->raop_rtp_mirror); @@ -237,100 +237,100 @@ conn_destroy(void *ptr) conn->raop->callbacks.video_flush(conn->raop->callbacks.cls); - free(conn->local); - free(conn->remote); - pairing_session_destroy(conn->pairing); - fairplay_destroy(conn->fairplay); - free(conn); + free(conn->local); + free(conn->remote); + pairing_session_destroy(conn->pairing); + fairplay_destroy(conn->fairplay); + free(conn); } raop_t * raop_init(int max_clients, raop_callbacks_t *callbacks) { - raop_t *raop; - pairing_t *pairing; - httpd_t *httpd; - httpd_callbacks_t httpd_cbs; - - assert(callbacks); - assert(max_clients > 0); - assert(max_clients < 100); - - /* Initialize the network */ - if (netutils_init() < 0) { - return NULL; - } - - /* Validate the callbacks structure */ - if (!callbacks->audio_process || - !callbacks->video_process) { - return NULL; - } - - /* Allocate the raop_t structure */ - raop = calloc(1, sizeof(raop_t)); - if (!raop) { - return NULL; - } - - /* Initialize the logger */ - raop->logger = logger_init(); - pairing = pairing_init_generate(); - if (!pairing) { - free(raop); - return NULL; - } - - /* Set HTTP callbacks to our handlers */ - memset(&httpd_cbs, 0, sizeof(httpd_cbs)); - httpd_cbs.opaque = raop; - httpd_cbs.conn_init = &conn_init; - httpd_cbs.conn_request = &conn_request; - httpd_cbs.conn_destroy = &conn_destroy; - - /* Initialize the http daemon */ - httpd = httpd_init(raop->logger, &httpd_cbs, max_clients); - if (!httpd) { - pairing_destroy(pairing); - free(raop); - return NULL; - } - /* Copy callbacks structure */ - memcpy(&raop->callbacks, callbacks, sizeof(raop_callbacks_t)); - raop->pairing = pairing; - raop->httpd = httpd; - return raop; + raop_t *raop; + pairing_t *pairing; + httpd_t *httpd; + httpd_callbacks_t httpd_cbs; + + assert(callbacks); + assert(max_clients > 0); + assert(max_clients < 100); + + /* Initialize the network */ + if (netutils_init() < 0) { + return NULL; + } + + /* Validate the callbacks structure */ + if (!callbacks->audio_process || + !callbacks->video_process) { + return NULL; + } + + /* Allocate the raop_t structure */ + raop = calloc(1, sizeof(raop_t)); + if (!raop) { + return NULL; + } + + /* Initialize the logger */ + raop->logger = logger_init(); + pairing = pairing_init_generate(); + if (!pairing) { + free(raop); + return NULL; + } + + /* Set HTTP callbacks to our handlers */ + memset(&httpd_cbs, 0, sizeof(httpd_cbs)); + httpd_cbs.opaque = raop; + httpd_cbs.conn_init = &conn_init; + httpd_cbs.conn_request = &conn_request; + httpd_cbs.conn_destroy = &conn_destroy; + + /* Initialize the http daemon */ + httpd = httpd_init(raop->logger, &httpd_cbs, max_clients); + if (!httpd) { + pairing_destroy(pairing); + free(raop); + return NULL; + } + /* Copy callbacks structure */ + memcpy(&raop->callbacks, callbacks, sizeof(raop_callbacks_t)); + raop->pairing = pairing; + raop->httpd = httpd; + return raop; } void raop_destroy(raop_t *raop) { - if (raop) { - raop_stop(raop); + if (raop) { + raop_stop(raop); pairing_destroy(raop->pairing); httpd_destroy(raop->httpd); logger_destroy(raop->logger); free(raop); - /* Cleanup the network */ - netutils_cleanup(); + /* Cleanup the network */ + netutils_cleanup(); } } int raop_is_running(raop_t *raop) { - assert(raop); + assert(raop); - return httpd_is_running(raop->httpd); + return httpd_is_running(raop->httpd); } void raop_set_log_level(raop_t *raop, int level) { - assert(raop); + assert(raop); - logger_set_level(raop->logger, level); + logger_set_level(raop->logger, level); } void @@ -357,30 +357,30 @@ raop_get_callback_cls(raop_t *raop) void raop_set_log_callback(raop_t *raop, raop_log_callback_t callback, void *cls) { - assert(raop); + assert(raop); - logger_set_callback(raop->logger, callback, cls); + logger_set_callback(raop->logger, callback, cls); } -void +void raop_set_dnssd(raop_t *raop, dnssd_t *dnssd) { - assert(dnssd); - raop->dnssd = dnssd; + assert(dnssd); + raop->dnssd = dnssd; } int raop_start(raop_t *raop, unsigned short *port) { - assert(raop); - assert(port); - return httpd_start(raop->httpd, port); + assert(raop); + assert(port); + return httpd_start(raop->httpd, port); } void raop_stop(raop_t *raop) { - assert(raop); - httpd_stop(raop->httpd); + assert(raop); + httpd_stop(raop->httpd); } \ No newline at end of file diff --git a/lib/raop_buffer.c b/lib/raop_buffer.c index d8fa9ef6..1352e934 100755 --- a/lib/raop_buffer.c +++ b/lib/raop_buffer.c @@ -59,9 +59,9 @@ struct raop_buffer_s { void raop_buffer_init_key_iv(raop_buffer_t *raop_buffer, - const unsigned char *aeskey, - const unsigned char *aesiv, - const unsigned char *ecdh_secret) + const unsigned char *aeskey, + const unsigned char *aesiv, + const unsigned char *ecdh_secret) { // Initialization key @@ -73,17 +73,17 @@ raop_buffer_init_key_iv(raop_buffer_t *raop_buffer, sha_update(ctx, ecdh_secret, 32); sha_final(ctx, eaeskey, NULL); sha_destroy(ctx); - + memcpy(raop_buffer->aeskey, eaeskey, 16); memcpy(raop_buffer->aesiv, aesiv, RAOP_AESIV_LEN); - #ifdef DUMP_AUDIO +#ifdef DUMP_AUDIO if (file_keyiv != NULL) { fwrite(raop_buffer->aeskey, 16, 1, file_keyiv); fwrite(raop_buffer->aesiv, 16, 1, file_keyiv); fclose(file_keyiv); } - #endif +#endif } raop_buffer_t * @@ -124,25 +124,25 @@ raop_buffer_destroy(raop_buffer_t *raop_buffer) } } - if (raop_buffer) { - free(raop_buffer); - } + if (raop_buffer) { + free(raop_buffer); + } - #ifdef DUMP_AUDIO +#ifdef DUMP_AUDIO if (file_aac != NULL) { fclose(file_aac); } if (file_source != NULL) { fclose(file_source); } - #endif +#endif } static short seqnum_cmp(unsigned short s1, unsigned short s2) { - return (s1 - s2); + return (s1 - s2); } //#define DUMP_AUDIO @@ -159,7 +159,7 @@ raop_buffer_decrypt(raop_buffer_t *raop_buffer, unsigned char *data, unsigned ch { assert(raop_buffer); int encryptedlen; - #ifdef DUMP_AUDIO +#ifdef DUMP_AUDIO if (file_aac == NULL) { file_aac = fopen("/home/pi/Airplay.aac", "wb"); file_source = fopen("/home/pi/Airplay.source", "wb"); @@ -169,7 +169,7 @@ raop_buffer_decrypt(raop_buffer_t *raop_buffer, unsigned char *data, unsigned ch if (file_source != NULL) { fwrite(&data[12], payloadsize, 1, file_source); } - #endif +#endif encryptedlen = payload_size / 16*16; memset(output, 0, payload_size); @@ -181,12 +181,12 @@ raop_buffer_decrypt(raop_buffer_t *raop_buffer, unsigned char *data, unsigned ch memcpy(output + encryptedlen, &data[12 + encryptedlen], payload_size - encryptedlen); *outputlen = payload_size; - #ifdef DUMP_AUDIO +#ifdef DUMP_AUDIO // Decrypted file if (file_aac != NULL) { fwrite(output, payloadsize, 1, file_aac); } - #endif +#endif return 1; } diff --git a/lib/raop_buffer.h b/lib/raop_buffer.h index 7ed77468..b03ed5d9 100755 --- a/lib/raop_buffer.h +++ b/lib/raop_buffer.h @@ -25,14 +25,14 @@ typedef int (*raop_resend_cb_t)(void *opaque, unsigned short seqno, unsigned sho raop_buffer_t *raop_buffer_init(logger_t *logger, const unsigned char *aeskey, const unsigned char *aesiv, - const unsigned char *ecdh_secret); + const unsigned char *ecdh_secret); int raop_buffer_enqueue(raop_buffer_t *raop_buffer, unsigned char *data, unsigned short datalen, uint64_t timestamp, int use_seqnum); void *raop_buffer_dequeue(raop_buffer_t *raop_buffer, unsigned int *length, uint64_t *timestamp, int no_resend); void raop_buffer_handle_resends(raop_buffer_t *raop_buffer, raop_resend_cb_t resend_cb, void *opaque); void raop_buffer_flush(raop_buffer_t *raop_buffer, int next_seq); -int raop_buffer_decrypt(raop_buffer_t *raop_buffer, unsigned char *data, unsigned char* output, - unsigned int datalen, unsigned int *outputlen); +int raop_buffer_decrypt(raop_buffer_t *raop_buffer, unsigned char *data, unsigned char* output, + unsigned int datalen, unsigned int *outputlen); void raop_buffer_destroy(raop_buffer_t *raop_buffer); #endif diff --git a/lib/raop_handlers.h b/lib/raop_handlers.h index 02ffe733..50d16986 100755 --- a/lib/raop_handlers.h +++ b/lib/raop_handlers.h @@ -26,8 +26,8 @@ typedef void (*raop_handler_t)(raop_conn_t *, http_request_t *, static void raop_handler_info(raop_conn_t *conn, - http_request_t *request, http_response_t *response, - char **response_data, int *response_datalen) + http_request_t *request, http_response_t *response, + char **response_data, int *response_datalen) { assert(conn->raop->dnssd); @@ -209,49 +209,49 @@ raop_handler_pairverify(raop_conn_t *conn, return; } switch (data[0]) { - case 1: - if (datalen != 4 + 32 + 32) { - logger_log(conn->raop->logger, LOGGER_ERR, "Invalid pair-verify data"); - return; - } - /* We can fall through these errors, the result will just be garbage... */ - if (pairing_session_handshake(conn->pairing, data + 4, data + 4 + 32)) { - logger_log(conn->raop->logger, LOGGER_ERR, "Error initializing pair-verify handshake"); - } - if (pairing_session_get_public_key(conn->pairing, public_key)) { - logger_log(conn->raop->logger, LOGGER_ERR, "Error getting ECDH public key"); - } - if (pairing_session_get_signature(conn->pairing, signature)) { - logger_log(conn->raop->logger, LOGGER_ERR, "Error getting ED25519 signature"); - } - *response_data = malloc(sizeof(public_key) + sizeof(signature)); - if (*response_data) { - http_response_add_header(response, "Content-Type", "application/octet-stream"); - memcpy(*response_data, public_key, sizeof(public_key)); - memcpy(*response_data + sizeof(public_key), signature, sizeof(signature)); - *response_datalen = sizeof(public_key) + sizeof(signature); - } - break; - case 0: - if (datalen != 4 + 64) { - logger_log(conn->raop->logger, LOGGER_ERR, "Invalid pair-verify data"); - return; - } + case 1: + if (datalen != 4 + 32 + 32) { + logger_log(conn->raop->logger, LOGGER_ERR, "Invalid pair-verify data"); + return; + } + /* We can fall through these errors, the result will just be garbage... */ + if (pairing_session_handshake(conn->pairing, data + 4, data + 4 + 32)) { + logger_log(conn->raop->logger, LOGGER_ERR, "Error initializing pair-verify handshake"); + } + if (pairing_session_get_public_key(conn->pairing, public_key)) { + logger_log(conn->raop->logger, LOGGER_ERR, "Error getting ECDH public key"); + } + if (pairing_session_get_signature(conn->pairing, signature)) { + logger_log(conn->raop->logger, LOGGER_ERR, "Error getting ED25519 signature"); + } + *response_data = malloc(sizeof(public_key) + sizeof(signature)); + if (*response_data) { + http_response_add_header(response, "Content-Type", "application/octet-stream"); + memcpy(*response_data, public_key, sizeof(public_key)); + memcpy(*response_data + sizeof(public_key), signature, sizeof(signature)); + *response_datalen = sizeof(public_key) + sizeof(signature); + } + break; + case 0: + if (datalen != 4 + 64) { + logger_log(conn->raop->logger, LOGGER_ERR, "Invalid pair-verify data"); + return; + } - if (pairing_session_finish(conn->pairing, data + 4)) { - logger_log(conn->raop->logger, LOGGER_ERR, "Incorrect pair-verify signature"); - http_response_set_disconnect(response, 1); - return; - } - http_response_add_header(response, "Content-Type", "application/octet-stream"); - break; + if (pairing_session_finish(conn->pairing, data + 4)) { + logger_log(conn->raop->logger, LOGGER_ERR, "Incorrect pair-verify signature"); + http_response_set_disconnect(response, 1); + return; + } + http_response_add_header(response, "Content-Type", "application/octet-stream"); + break; } } static void raop_handler_fpsetup(raop_conn_t *conn, - http_request_t *request, http_response_t *response, - char **response_data, int *response_datalen) + http_request_t *request, http_response_t *response, + char **response_data, int *response_datalen) { const unsigned char *data; int datalen; @@ -557,16 +557,16 @@ raop_handler_set_parameter(raop_conn_t *conn, static void raop_handler_feedback(raop_conn_t *conn, - http_request_t *request, http_response_t *response, - char **response_data, int *response_datalen) + http_request_t *request, http_response_t *response, + char **response_data, int *response_datalen) { logger_log(conn->raop->logger, LOGGER_DEBUG, "raop_handler_feedback"); } static void raop_handler_record(raop_conn_t *conn, - http_request_t *request, http_response_t *response, - char **response_data, int *response_datalen) + http_request_t *request, http_response_t *response, + char **response_data, int *response_datalen) { logger_log(conn->raop->logger, LOGGER_DEBUG, "raop_handler_record"); http_response_add_header(response, "Audio-Latency", "11025"); diff --git a/lib/raop_ntp.c b/lib/raop_ntp.c index b4007d7b..214d5cd5 100644 --- a/lib/raop_ntp.c +++ b/lib/raop_ntp.c @@ -39,8 +39,8 @@ typedef struct raop_ntp_data_s { uint64_t time; // The local wall clock time at time of ntp packet arrival uint64_t dispersion; - int64_t delay; // The round trip delay - int64_t offset; // The difference between remote and local wall clock time + int64_t delay; // The round trip delay + int64_t offset; // The difference between remote and local wall clock time } raop_ntp_data_t; struct raop_ntp_s { @@ -52,8 +52,8 @@ struct raop_ntp_s { mutex_handle_t wait_mutex; cond_handle_t wait_cond; - raop_ntp_data_t data[RAOP_NTP_DATA_COUNT]; - int data_index; + raop_ntp_data_t data[RAOP_NTP_DATA_COUNT]; + int data_index; // The clock sync params are periodically updated to the AirPlay client's NTP clock mutex_handle_t sync_params_mutex; diff --git a/lib/raop_rtp.c b/lib/raop_rtp.c index 2726b2de..d31cfef3 100755 --- a/lib/raop_rtp.c +++ b/lib/raop_rtp.c @@ -133,7 +133,7 @@ raop_rtp_parse_remote(raop_rtp_t *raop_rtp, const unsigned char *remote, int rem raop_rtp_t * raop_rtp_init(logger_t *logger, raop_callbacks_t *callbacks, raop_ntp_t *ntp, const unsigned char *remote, int remotelen, - const unsigned char *aeskey, const unsigned char *aesiv, const unsigned char *ecdh_secret) + const unsigned char *aeskey, const unsigned char *aesiv, const unsigned char *ecdh_secret) { raop_rtp_t *raop_rtp; @@ -162,9 +162,9 @@ raop_rtp_init(logger_t *logger, raop_callbacks_t *callbacks, raop_ntp_t *ntp, co return NULL; } if (raop_rtp_parse_remote(raop_rtp, remote, remotelen) < 0) { - free(raop_rtp); - return NULL; - } + free(raop_rtp); + return NULL; + } raop_rtp->running = 0; raop_rtp->joined = 1; @@ -395,7 +395,7 @@ raop_rtp_thread_udp(void *arg) unsigned int packetlen; struct sockaddr_storage saddr; socklen_t saddrlen; - assert(raop_rtp); + assert(raop_rtp); while(1) { fd_set rfds; @@ -431,37 +431,37 @@ raop_rtp_thread_udp(void *arg) } if (FD_ISSET(raop_rtp->csock, &rfds)) { - saddrlen = sizeof(saddr); - packetlen = recvfrom(raop_rtp->csock, (char *)packet, sizeof(packet), 0, - (struct sockaddr *)&saddr, &saddrlen); - - memcpy(&raop_rtp->control_saddr, &saddr, saddrlen); - raop_rtp->control_saddr_len = saddrlen; - int type_c = packet[1] & ~0x80; - logger_log(raop_rtp->logger, LOGGER_DEBUG, "raop_rtp type_c 0x%02x, packetlen = %d", type_c, packetlen); - if (type_c == 0x56) { - /* Handle resent data packet */ - uint32_t rtp_timestamp = (packet[4 + 4] << 24) | (packet[4 + 5] << 16) | (packet[4 + 6] << 8) | packet[4 + 7]; - uint64_t ntp_timestamp = raop_rtp_convert_rtp_time(raop_rtp, rtp_timestamp); - uint64_t ntp_now = raop_ntp_get_local_time(raop_rtp->ntp); - logger_log(raop_rtp->logger, LOGGER_DEBUG, "raop_rtp audio resent: ntp = %llu, now = %llu, latency=%lld, rtp=%u", - ntp_timestamp, ntp_now, ((int64_t) ntp_now) - ((int64_t) ntp_timestamp), rtp_timestamp); - int result = raop_buffer_enqueue(raop_rtp->buffer, packet + 4, packetlen - 4, ntp_timestamp, 1); - assert(result >= 0); - } else if (type_c == 0x54 && packetlen >= 20) { - // The unit for the rtp clock is 1 / sample rate = 1 / 44100 - uint32_t sync_rtp = byteutils_get_int_be(packet, 4) - 11025; - uint64_t sync_ntp_raw = byteutils_get_long_be(packet, 8); - uint64_t sync_ntp_remote = raop_ntp_timestamp_to_micro_seconds(sync_ntp_raw, true); - uint64_t sync_ntp_local = raop_ntp_convert_remote_time(raop_rtp->ntp, sync_ntp_remote); - // It's not clear what the additional rtp timestamp indicates - uint32_t next_rtp = byteutils_get_int_be(packet, 16); - logger_log(raop_rtp->logger, LOGGER_DEBUG, "raop_rtp sync: ntp=%llu, local ntp: %llu, rtp=%u, rtp_next=%u", - sync_ntp_remote, sync_ntp_local, sync_rtp, next_rtp); - raop_rtp_sync_clock(raop_rtp, sync_rtp, sync_ntp_local); - } else { - logger_log(raop_rtp->logger, LOGGER_DEBUG, "raop_rtp unknown packet"); - } + saddrlen = sizeof(saddr); + packetlen = recvfrom(raop_rtp->csock, (char *)packet, sizeof(packet), 0, + (struct sockaddr *)&saddr, &saddrlen); + + memcpy(&raop_rtp->control_saddr, &saddr, saddrlen); + raop_rtp->control_saddr_len = saddrlen; + int type_c = packet[1] & ~0x80; + logger_log(raop_rtp->logger, LOGGER_DEBUG, "raop_rtp type_c 0x%02x, packetlen = %d", type_c, packetlen); + if (type_c == 0x56) { + /* Handle resent data packet */ + uint32_t rtp_timestamp = (packet[4 + 4] << 24) | (packet[4 + 5] << 16) | (packet[4 + 6] << 8) | packet[4 + 7]; + uint64_t ntp_timestamp = raop_rtp_convert_rtp_time(raop_rtp, rtp_timestamp); + uint64_t ntp_now = raop_ntp_get_local_time(raop_rtp->ntp); + logger_log(raop_rtp->logger, LOGGER_DEBUG, "raop_rtp audio resent: ntp = %llu, now = %llu, latency=%lld, rtp=%u", + ntp_timestamp, ntp_now, ((int64_t) ntp_now) - ((int64_t) ntp_timestamp), rtp_timestamp); + int result = raop_buffer_enqueue(raop_rtp->buffer, packet + 4, packetlen - 4, ntp_timestamp, 1); + assert(result >= 0); + } else if (type_c == 0x54 && packetlen >= 20) { + // The unit for the rtp clock is 1 / sample rate = 1 / 44100 + uint32_t sync_rtp = byteutils_get_int_be(packet, 4) - 11025; + uint64_t sync_ntp_raw = byteutils_get_long_be(packet, 8); + uint64_t sync_ntp_remote = raop_ntp_timestamp_to_micro_seconds(sync_ntp_raw, true); + uint64_t sync_ntp_local = raop_ntp_convert_remote_time(raop_rtp->ntp, sync_ntp_remote); + // It's not clear what the additional rtp timestamp indicates + uint32_t next_rtp = byteutils_get_int_be(packet, 16); + logger_log(raop_rtp->logger, LOGGER_DEBUG, "raop_rtp sync: ntp=%llu, local ntp: %llu, rtp=%u, rtp_next=%u", + sync_ntp_remote, sync_ntp_local, sync_rtp, next_rtp); + raop_rtp_sync_clock(raop_rtp, sync_rtp, sync_ntp_local); + } else { + logger_log(raop_rtp->logger, LOGGER_DEBUG, "raop_rtp unknown packet"); + } } if (FD_ISSET(raop_rtp->dsock, &rfds)) { @@ -482,7 +482,7 @@ raop_rtp_thread_udp(void *arg) uint64_t ntp_timestamp = raop_rtp_convert_rtp_time(raop_rtp, rtp_timestamp); uint64_t ntp_now = raop_ntp_get_local_time(raop_rtp->ntp); logger_log(raop_rtp->logger, LOGGER_DEBUG, "raop_rtp audio: ntp = %llu, now = %llu, latency=%lld, rtp=%u", - ntp_timestamp, ntp_now, ((int64_t) ntp_now) - ((int64_t) ntp_timestamp), rtp_timestamp); + ntp_timestamp, ntp_now, ((int64_t) ntp_now) - ((int64_t) ntp_timestamp), rtp_timestamp); int result = raop_buffer_enqueue(raop_rtp->buffer, packet, packetlen, ntp_timestamp, 1); assert(result >= 0); diff --git a/lib/raop_rtp.h b/lib/raop_rtp.h index f23088ce..5d66b67a 100755 --- a/lib/raop_rtp.h +++ b/lib/raop_rtp.h @@ -27,10 +27,10 @@ typedef struct raop_rtp_s raop_rtp_t; raop_rtp_t *raop_rtp_init(logger_t *logger, raop_callbacks_t *callbacks, raop_ntp_t *ntp, const unsigned char *remote, int remotelen, - const unsigned char *aeskey, const unsigned char *aesiv, const unsigned char *ecdh_secret); + const unsigned char *aeskey, const unsigned char *aesiv, const unsigned char *ecdh_secret); void raop_rtp_start_audio(raop_rtp_t *raop_rtp, int use_udp, unsigned short control_rport, - unsigned short *control_lport, unsigned short *data_lport); + unsigned short *control_lport, unsigned short *data_lport); void raop_rtp_set_volume(raop_rtp_t *raop_rtp, float volume); void raop_rtp_set_metadata(raop_rtp_t *raop_rtp, const char *data, int datalen); diff --git a/lib/raop_rtp_mirror.c b/lib/raop_rtp_mirror.c index c75cb361..8ccdcda4 100755 --- a/lib/raop_rtp_mirror.c +++ b/lib/raop_rtp_mirror.c @@ -150,20 +150,20 @@ raop_rtp_mirror_thread(void *arg) { raop_rtp_mirror_t *raop_rtp_mirror = arg; assert(raop_rtp_mirror); - + int stream_fd = -1; unsigned char packet[128]; memset(packet, 0 , 128); unsigned char* payload = NULL; unsigned int readstart = 0; - #ifdef DUMP_H264 +#ifdef DUMP_H264 // C decrypted FILE* file = fopen("/home/pi/Airplay.h264", "wb"); // Encrypted source file FILE* file_source = fopen("/home/pi/Airplay.source", "wb"); FILE* file_len = fopen("/home/pi/Airplay.len", "wb"); - #endif +#endif while (1) { fd_set rfds; @@ -247,17 +247,17 @@ raop_rtp_mirror_thread(void *arg) unsigned short payload_option = byteutils_get_short(packet, 6); if (payload == NULL) { - payload = malloc(payload_size); + payload = malloc(payload_size); readstart = 0; - } - + } + while (readstart < payload_size) { // Payload data ret = recv(stream_fd, payload + readstart, payload_size - readstart, 0); if (ret <= 0) break; readstart = readstart + ret; } - + if (ret == 0) { logger_log(raop_rtp_mirror->logger, LOGGER_ERR, "raop_rtp_mirror tcp socket closed"); break; @@ -282,10 +282,10 @@ raop_rtp_mirror_thread(void *arg) logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "raop_rtp_mirror video ntp = %llu, now = %llu, latency = %lld", ntp_timestamp, ntp_now, ((int64_t) ntp_now) - ((int64_t) ntp_timestamp)); - #ifdef DUMP_H264 +#ifdef DUMP_H264 fwrite(payload, payload_size, 1, file_source); fwrite(&readstart, sizeof(readstart), 1, file_len); - #endif +#endif // Decrypt data unsigned char* payload_decrypted = malloc(payload_size); @@ -314,9 +314,9 @@ raop_rtp_mirror_thread(void *arg) // logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "nalu_size = %d, payloadsize = %d nalus_count = %d", // nalu_size, payload_size, nalus_count); - #ifdef DUMP_H264 +#ifdef DUMP_H264 fwrite(payload_decrypted, payload_size, 1, file); - #endif +#endif h264_decode_struct h264_data; h264_data.data_len = payload_size; @@ -370,9 +370,9 @@ raop_rtp_mirror_thread(void *arg) sps_pps[h264.sps_size + 7] = 1; memcpy(sps_pps + h264.sps_size + 8, h264.picture_parameter_set, h264.pps_size); - #ifdef DUMP_H264 +#ifdef DUMP_H264 fwrite(sps_pps, sps_pps_len, 1, file); - #endif +#endif h264_decode_struct h264_data; h264_data.data_len = sps_pps_len; @@ -397,11 +397,11 @@ raop_rtp_mirror_thread(void *arg) closesocket(stream_fd); } - #ifdef DUMP_H264 - fclose(file); +#ifdef DUMP_H264 + fclose(file); fclose(file_source); fclose(file_len); - #endif +#endif // Ensure running reflects the actual state MUTEX_LOCK(raop_rtp_mirror->run_mutex); diff --git a/renderers/audio_renderer_rpi.c b/renderers/audio_renderer_rpi.c index 13cf6309..db922c42 100644 --- a/renderers/audio_renderer_rpi.c +++ b/renderers/audio_renderer_rpi.c @@ -88,7 +88,7 @@ int audio_renderer_init_decoder(audio_renderer_t *renderer) { logger_log(renderer->logger, LOGGER_DEBUG, "> stream info: channel = %d\tsample_rate = %d\tframe_size = %d\taot = %d\tbitrate = %d", \ aac_stream_info->channelConfig, aac_stream_info->aacSampleRate, - aac_stream_info->aacSamplesPerFrame, aac_stream_info->aot, aac_stream_info->bitRate); + aac_stream_info->aacSamplesPerFrame, aac_stream_info->aot, aac_stream_info->bitRate); return 1; } @@ -125,7 +125,7 @@ int audio_renderer_init_renderer(audio_renderer_t *renderer, video_renderer_t *v // Create audio_renderer if (ilclient_create_component(renderer->client, &renderer->audio_renderer, "audio_render", - ILCLIENT_DISABLE_ALL_PORTS | ILCLIENT_ENABLE_INPUT_BUFFERS) != 0) { + ILCLIENT_DISABLE_ALL_PORTS | ILCLIENT_ENABLE_INPUT_BUFFERS) != 0) { audio_renderer_destroy_renderer(renderer); return -14; } @@ -163,7 +163,7 @@ int audio_renderer_init_renderer(audio_renderer_t *renderer, video_renderer_t *v clock_state.eState = OMX_TIME_ClockStateWaitingForStartTime; clock_state.nWaitMask = 1; if (OMX_SetParameter(ilclient_get_handle(renderer->clock), OMX_IndexConfigTimeClockState, - &clock_state) != OMX_ErrorNone) { + &clock_state) != OMX_ErrorNone) { audio_renderer_destroy_decoder(renderer); return -13; } @@ -187,7 +187,7 @@ int audio_renderer_init_renderer(audio_renderer_t *renderer, video_renderer_t *v port_format.nPortIndex = 100; port_format.eEncoding = OMX_AUDIO_CodingPCM; if (OMX_SetParameter(ilclient_get_handle(renderer->audio_renderer), OMX_IndexParamAudioPortFormat, - &port_format) != OMX_ErrorNone) { + &port_format) != OMX_ErrorNone) { logger_log(renderer->logger, LOGGER_DEBUG, "Could not set pcm format"); audio_renderer_destroy_renderer(renderer); return -13; @@ -208,7 +208,7 @@ int audio_renderer_init_renderer(audio_renderer_t *renderer, video_renderer_t *v pcm_mode.ePCMMode = OMX_AUDIO_PCMModeLinear; if (OMX_SetConfig(ilclient_get_handle(renderer->audio_renderer), OMX_IndexParamAudioPcm, - &pcm_mode) != OMX_ErrorNone) { + &pcm_mode) != OMX_ErrorNone) { logger_log(renderer->logger, LOGGER_DEBUG, "Could not set pcm config"); audio_renderer_destroy_renderer(renderer); return -13; @@ -223,7 +223,7 @@ int audio_renderer_init_renderer(audio_renderer_t *renderer, video_renderer_t *v strcpy((char *)audio_destination.sName, device_name); if (OMX_SetConfig(ilclient_get_handle(renderer->audio_renderer), OMX_IndexConfigBrcmAudioDestination, - &audio_destination) != OMX_ErrorNone) { + &audio_destination) != OMX_ErrorNone) { logger_log(renderer->logger, LOGGER_DEBUG, "Could not set audio device"); audio_renderer_destroy_renderer(renderer); return -14; @@ -349,7 +349,7 @@ void audio_renderer_set_volume(audio_renderer_t *renderer, float volume) { audio_volume.sVolume.nValue = volume * 200.0; if (OMX_SetConfig(ilclient_get_handle(renderer->audio_renderer), OMX_IndexConfigAudioVolume, - &audio_volume) != OMX_ErrorNone) { + &audio_volume) != OMX_ErrorNone) { logger_log(renderer->logger, LOGGER_DEBUG, "Could not set audio volume"); } } diff --git a/rpiplay.cpp b/rpiplay.cpp index 2283d3d3..02e03829 100755 --- a/rpiplay.cpp +++ b/rpiplay.cpp @@ -43,7 +43,7 @@ #define DEFAULT_HW_ADDRESS { (char) 0x48, (char) 0x5d, (char) 0x60, (char) 0x7c, (char) 0xee, (char) 0x22 } int start_server(std::vector hw_addr, std::string name, bool show_background, audio_device_t audio_device, - bool low_latency, bool debug_log); + bool low_latency, bool debug_log); int stop_server(); static bool running = false; @@ -54,10 +54,10 @@ static audio_renderer_t *audio_renderer = NULL; static void signal_handler(int sig) { switch (sig) { - case SIGINT: - case SIGTERM: - running = 0; - break; + case SIGINT: + case SIGTERM: + running = 0; + break; } } @@ -120,7 +120,7 @@ int main(int argc, char *argv[]) { if (i == argc - 1) continue; server_name = std::string(argv[++i]); } else if (arg == "-b") { - show_background = !show_background; + show_background = !show_background; } else if (arg == "-a") { if (i == argc - 1) continue; std::string audio_device_name(argv[++i]); @@ -142,7 +142,7 @@ int main(int argc, char *argv[]) { server_hw_addr.clear(); parse_hw_addr(mac_address, server_hw_addr); } - + if (start_server(server_hw_addr, server_name, show_background, audio_device, low_latency, debug_log) != 0) { return 1; } @@ -206,7 +206,7 @@ extern "C" void log_callback(void *cls, int level, const char *msg) { } int start_server(std::vector hw_addr, std::string name, bool show_background, audio_device_t audio_device, - bool low_latency, bool debug_log) { + bool low_latency, bool debug_log) { raop_callbacks_t raop_cbs; memset(&raop_cbs, 0, sizeof(raop_cbs)); raop_cbs.audio_process = audio_process; @@ -257,7 +257,7 @@ int start_server(std::vector hw_addr, std::string name, bool show_backgrou } raop_set_dnssd(raop, dnssd); - + dnssd_register_raop(dnssd, port); dnssd_register_airplay(dnssd, port + 1);