Started implementing a scanner with just playstatusupdate message

This commit is contained in:
Mike Brady
2017-12-03 20:11:23 +00:00
parent 88c550663c
commit 0f68ff0c9a
+127 -12
View File
@@ -39,12 +39,12 @@
#include <time.h>
#include <unistd.h>
typedef struct {
typedef struct {
uint16_t port;
short connection_family; // AF_INET6 or AF_INET
uint32_t scope_id; // if it's an ipv6 connection, this will be its scope id
short connection_family; // AF_INET6 or AF_INET
uint32_t scope_id; // if it's an ipv6 connection, this will be its scope id
char ip_string[INET6_ADDRSTRLEN]; // the ip string pointing to the client
uint32_t active_remote_id; // send this when you want to send remote control commands
uint32_t active_remote_id; // send this when you want to send remote control commands
} dacp_server_record;
pthread_t dacp_monitor_thread;
@@ -54,32 +54,147 @@ static pthread_mutex_t dacp_conversation_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t dacp_server_information_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t dacp_server_information_cv = PTHREAD_COND_INITIALIZER;
ssize_t dacp_send_command(const char *command, char *response, size_t max_response_length) {
ssize_t reply_size = -1;
// try to do this transaction on the DACP server, but don't wait for more than 20 ms to be allowed
// to do it.
struct timespec mutex_wait_time;
mutex_wait_time.tv_sec = 0;
mutex_wait_time.tv_nsec = 20000000; // 20 ms
struct addrinfo hints, *res;
int sockfd;
char message[20000], server_reply[2000], portstring[10], server[256];
memset(&message, 0, sizeof(message));
if ((response) && (max_response_length))
memset(response, 0, max_response_length);
else
memset(&server_reply, 0, sizeof(server_reply));
memset(&portstring, 0, sizeof(portstring));
if (dacp_server.connection_family == AF_INET6) {
sprintf(server, "%s%%%u", dacp_server.ip_string, dacp_server.scope_id);
} else {
strcpy(server, dacp_server.ip_string);
}
sprintf(portstring, "%u", dacp_server.port);
// first, load up address structs with getaddrinfo():
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
// debug(1, "DHCP port string is \"%s:%u\".", dacp_server.ip_string, dacp_server.port);
getaddrinfo(server, portstring, &hints, &res);
// only do this one at a time -- not sure it is necessary, but better safe than sorry
int mutex_reply = pthread_mutex_timedlock(&dacp_conversation_lock, &mutex_wait_time);
if (mutex_reply == 0) {
// make a socket:
sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (sockfd == -1) {
debug(1, "Could not create socket");
} else {
// connect!
if (connect(sockfd, res->ai_addr, res->ai_addrlen) < 0) {
debug(1, "connect failed. Error");
} else {
sprintf(message, "GET /ctrl-int/1/%s HTTP/1.1\r\nHost: %s:%u\r\nActive-Remote: %u\r\n\r\n",
command, dacp_server.ip_string, dacp_server.port, dacp_server.active_remote_id);
// Send command
if (send(sockfd, message, strlen(message), 0) < 0) {
debug(1, "Send failed");
}
// Receive a reply from the server
if ((response) && (max_response_length))
reply_size = recv(sockfd, response, max_response_length, 0);
else
reply_size = recv(sockfd, server_reply, sizeof(server_reply), 0);
if (reply_size < 0) {
debug(1, "recv failed");
}
close(sockfd);
}
}
pthread_mutex_unlock(&dacp_conversation_lock);
} else {
debug(1, "Could not acquire a lock on the dacp transmit/receive section. Possible timeout?");
}
return reply_size;
}
// this will be running on the thread of its caller, not of the conversation thread...
void set_dacp_server_information(rtsp_conn_info* conn) { // tell the DACP conversation thread that the port has been set or changed
void set_dacp_server_information(rtsp_conn_info *conn) { // tell the DACP conversation thread that
// the port has been set or changed
pthread_mutex_lock(&dacp_server_information_lock);
dacp_server.port = conn->dacp_port;
dacp_server.connection_family = conn->connection_ip_family;
dacp_server.scope_id = conn-> self_scope_id;
strncpy(dacp_server.ip_string,conn->client_ip_string,INET6_ADDRSTRLEN);
dacp_server.scope_id = conn->self_scope_id;
strncpy(dacp_server.ip_string, conn->client_ip_string, INET6_ADDRSTRLEN);
dacp_server.active_remote_id = conn->dacp_active_remote;
pthread_cond_signal(&dacp_server_information_cv);
pthread_mutex_unlock(&dacp_server_information_lock);
}
void *dacp_monitor_thread_code(void *na) {
int scan_index = 0;
char server_reply[2000];
debug(1, "DACP monitor thread started.");
// wait until we get a valid port number to begin monitoring it
while (1) {
pthread_mutex_lock(&dacp_server_information_lock);
while (dacp_server.port == 0) {
debug(1,"Wait for a valid DACP port");
debug(1, "Wait for a valid DACP port");
pthread_cond_wait(&dacp_server_information_cv, &dacp_server_information_lock);
}
pthread_mutex_unlock(&dacp_server_information_lock);
debug(1,"DACP Server ID \"%u\" at \"%s:%u\", scan %d.",dacp_server.active_remote_id,dacp_server.ip_string,dacp_server.port,scan_index++);
//debug(1, "DACP Server ID \"%u\" at \"%s:%u\", scan %d.", dacp_server.active_remote_id,
// dacp_server.ip_string, dacp_server.port, scan_index++);
ssize_t reply_size =
dacp_send_command("playstatusupdate", server_reply, sizeof(server_reply));
if (reply_size >= 0) {
// not interested in the response.
if (strstr(server_reply, "HTTP/1.1 204") == server_reply) {
debug(1,"Client response is No Content");
} else if (strstr(server_reply, "HTTP/1.1 501") == server_reply) {
debug(1,"Client response is \"Not Implemented\". DACP Server has disconnnected.");
dacp_server.port = 0; // stop scanning until the next time it's used
/*
} else {
debug(1,
"Client request to server responded with %d characters starting with this response:",
strlen(server_reply));
int i;
for (i = 0; i < reply_size; i++)
if (server_reply[i] < ' ')
debug(1, "%d %02x", i, server_reply[i]);
else
debug(1, "%d %02x '%c'", i, server_reply[i], server_reply[i]);
// sprintf((char *)message + 2 * i, "%02x", server_reply[i]);
// debug(1,"Content is \"%s\".",message);
*/
}
} else {
debug(1, "Error at rtp_send_client_command");
}
sleep(3);
}
debug(1, "DACP monitor thread exiting.");
@@ -87,7 +202,7 @@ void *dacp_monitor_thread_code(void *na) {
}
void dacp_monitor_start() {
memset(&dacp_server,0,sizeof(dacp_server_record));
memset(&dacp_server, 0, sizeof(dacp_server_record));
pthread_create(&dacp_monitor_thread, NULL, dacp_monitor_thread_code, NULL);
}