static void remove_remote(struct remote_info *ri) { unlink_remote(ri); free_remote(ri); }
void close_and_free_remote(EV_P_ struct remote *remote) { if (remote != NULL) { ev_timer_stop(EV_A_ &remote->send_ctx->watcher); ev_io_stop(EV_A_ &remote->send_ctx->io); ev_io_stop(EV_A_ &remote->recv_ctx->io); close(remote->fd); free_remote(remote); } }
static void do_pairing(struct remote_info *ri) { char req_uri[128]; char *pairing_hash; int ret; pairing_hash = itunes_pairing_hash(ri->paircode, ri->pin); if (!pairing_hash) { DPRINTF(E_LOG, L_REMOTE, "Could not compute pairing hash!\n"); goto hash_fail; } DPRINTF(E_DBG, L_REMOTE, "Pairing hash for %s/%s: %s\n", ri->pi.remote_id, ri->pi.name, pairing_hash); /* Prepare request URI */ /* The servicename variable is the mDNS service group name; currently it's * a hash of the library name, but in iTunes the service name and the library * ID (DbId) are different (see comment in main.c). * Remote uses the service name to perform mDNS lookups. */ ret = snprintf(req_uri, sizeof(req_uri), "/pair?pairingcode=%s&servicename=%016" PRIX64, pairing_hash, libhash); free(pairing_hash); if ((ret < 0) || (ret >= sizeof(req_uri))) { DPRINTF(E_WARN, L_REMOTE, "Request URI for pairing exceeds buffer size\n"); goto req_uri_fail; } /* Fire up the request */ if (ri->v6_address) { ret = send_pairing_request(ri, req_uri, AF_INET6); if (ret == 0) return; DPRINTF(E_WARN, L_REMOTE, "Could not send pairing request on IPv6\n"); } ret = send_pairing_request(ri, req_uri, AF_INET); if (ret < 0) { DPRINTF(E_WARN, L_REMOTE, "Could not send pairing request on IPv4\n"); goto pairing_fail; } return; pairing_fail: req_uri_fail: hash_fail: free_remote(ri); }
static void pairing_free_cb(void *arg) { struct remote_info *ri; ri = (struct remote_info *)arg; free_remote(ri); }
void close_and_free_remote(EV_P_ struct remote *remote) { if (remote != NULL) { ev_io_stop(EV_A_ &remote->send_ctx->io); ev_io_stop(EV_A_ &remote->recv_ctx->io); close(remote->fd); free_remote(remote); } if (verbose) { LOGD("current remote connection: %d", remote_conn); } }
/* Thread: main */ void remote_pairing_deinit(void) { struct remote_info *ri; for (ri = remote_list; remote_list; ri = remote_list) { remote_list = ri->next; free_remote(ri); } #ifdef USE_EVENTFD close(pairing_efd); #else close(pairing_pipe[0]); close(pairing_pipe[1]); #endif }
static void remote_close_cb(uv_handle_t *handle) { struct remote_context *remote = handle->data; free_remote(remote); }
/* Thread: main (pairing) */ static void pairing_request_cb(struct evhttp_request *req, void *arg) { struct remote_info *ri; uint8_t *response; char guid[17]; int len; int i; int ret; ri = (struct remote_info *)arg; if (!req) goto cleanup; if (req->response_code != HTTP_OK) { DPRINTF(E_LOG, L_REMOTE, "Pairing failed with Remote %s/%s, HTTP response code %d\n", ri->pi.remote_id, ri->pi.name, req->response_code); goto cleanup; } if (EVBUFFER_LENGTH(req->input_buffer) < 8) { DPRINTF(E_LOG, L_REMOTE, "Remote %s/%s: pairing response too short\n", ri->pi.remote_id, ri->pi.name); goto cleanup; } response = EVBUFFER_DATA(req->input_buffer); if ((response[0] != 'c') || (response[1] != 'm') || (response[2] != 'p') || (response[3] != 'a')) { DPRINTF(E_LOG, L_REMOTE, "Remote %s/%s: unknown pairing response, expected cmpa\n", ri->pi.remote_id, ri->pi.name); goto cleanup; } len = (response[4] << 24) | (response[5] << 16) | (response[6] << 8) | (response[7]); if (EVBUFFER_LENGTH(req->input_buffer) < 8 + len) { DPRINTF(E_LOG, L_REMOTE, "Remote %s/%s: pairing response truncated (got %d expected %d)\n", ri->pi.remote_id, ri->pi.name, (int)EVBUFFER_LENGTH(req->input_buffer), len + 8); goto cleanup; } response += 8; for (; len > 0; len--, response++) { if ((response[0] != 'c') || (response[1] != 'm') || (response[2] != 'p') || (response[3] != 'g')) continue; else { len -= 8; response += 8; break; } } if (len < 8) { DPRINTF(E_LOG, L_REMOTE, "Remote %s/%s: cmpg truncated in pairing response\n", ri->pi.remote_id, ri->pi.name); goto cleanup; } for (i = 0; i < 8; i++) sprintf(guid + (2 * i), "%02X", response[i]); ri->pi.guid = strdup(guid); DPRINTF(E_INFO, L_REMOTE, "Pairing succeeded with Remote '%s' (id %s), GUID: %s\n", ri->pi.name, ri->pi.remote_id, guid); ret = db_pairing_add(&ri->pi); if (ret < 0) { DPRINTF(E_LOG, L_REMOTE, "Failed to register pairing!\n"); goto cleanup; } cleanup: evhttp_connection_free(ri->evcon); free_remote(ri); }