Exemplo n.º 1
0
int mpd_set_connection_timeout(MpdObj *mi, float timeout)
{
	if(mi == NULL)
	{
		debug_printf(DEBUG_ERROR, "mi == NULL\n");
		return MPD_ARGS_ERROR;
	}
	mi->connection_timeout = timeout;
	if(mpd_check_connected(mi))
	{
		/*TODO: set timeout */	
		if(mpd_lock_conn(mi))
		{
			debug_printf(DEBUG_ERROR,"lock failed\n");
			return MPD_LOCK_FAILED;
		}
		mpd_setConnectionTimeout(mi->connection, timeout);
		mpd_finishCommand(mi->connection);

		mpd_unlock_conn(mi);

	}
	return MPD_OK;
}
Exemplo n.º 2
0
mpd_Connection * mpd_newConnection(const char * host, int port, float timeout) {
	int err;
	struct hostent * he;
	struct sockaddr * dest;
#ifdef HAVE_SOCKLEN_T
	socklen_t destlen;
#else
	int destlen;
#endif
	struct sockaddr_in sin;
	char * rt;
	char * output;
	mpd_Connection * connection = malloc(sizeof(mpd_Connection));
	struct timeval tv;
	fd_set fds;
#ifdef MPD_HAVE_IPV6
	struct sockaddr_in6 sin6;
#endif
	strcpy(connection->buffer,"");
	connection->buflen = 0;
	connection->bufstart = 0;
	strcpy(connection->errorStr,"");
	connection->error = 0;
	connection->doneProcessing = 0;
	connection->commandList = 0;
	connection->listOks = 0;
	connection->doneListOk = 0;
	connection->returnElement = NULL;

	if(!(he=gethostbyname(host))) {
		snprintf(connection->errorStr,MPD_BUFFER_MAX_LENGTH,
				"host \"%s\" not found",host);
		connection->error = MPD_ERROR_UNKHOST;
		return connection;
	}

	memset(&sin,0,sizeof(struct sockaddr_in));
	/*dest.sin_family = he->h_addrtype;*/
	sin.sin_family = AF_INET;
	sin.sin_port = htons(port);
#ifdef MPD_HAVE_IPV6
	memset(&sin6,0,sizeof(struct sockaddr_in6));
	sin6.sin6_family = AF_INET6;
	sin6.sin6_port = htons(port);
#endif
	switch(he->h_addrtype) {
	case AF_INET:
		memcpy((char *)&sin.sin_addr.s_addr,(char *)he->h_addr,
				he->h_length);
		dest = (struct sockaddr *)&sin;
		destlen = sizeof(struct sockaddr_in);
		break;
#ifdef MPD_HAVE_IPV6
	case AF_INET6:
		if(!mpd_ipv6Supported()) {
			strcpy(connection->errorStr,"no IPv6 suuport but a "
					"IPv6 address found\n");
			connection->error = MPD_ERROR_SYSTEM;
			return connection;
		}
		memcpy((char *)&sin6.sin6_addr.s6_addr,(char *)he->h_addr,
				he->h_length);
		dest = (struct sockaddr *)&sin6;
		destlen = sizeof(struct sockaddr_in6);
		break;
#endif
	default:
		strcpy(connection->errorStr,"address type is not IPv4 or "
				"IPv6\n");
		connection->error = MPD_ERROR_SYSTEM;
		return connection;
		break;
	}
	
	if((connection->sock = socket(dest->sa_family,SOCK_STREAM,0))<0) {
		strcpy(connection->errorStr,"problems creating socket");
		connection->error = MPD_ERROR_SYSTEM;
		return connection;
	}

	mpd_setConnectionTimeout(connection,timeout);

	/* connect stuff */
	{
		int flags = fcntl(connection->sock, F_GETFL, 0);
		fcntl(connection->sock, F_SETFL, flags | O_NONBLOCK);

		if(connect(connection->sock,dest,destlen)<0 && 
				errno!=EINPROGRESS) 
		{
			snprintf(connection->errorStr,MPD_BUFFER_MAX_LENGTH,
					"problems connecting to \"%s\" on port"
				 	" %i",host,port);
			connection->error = MPD_ERROR_CONNPORT;
			return connection;
		}
	}

	while(!(rt = strstr(connection->buffer,"\n"))) {
		tv.tv_sec = connection->timeout.tv_sec;
		tv.tv_usec = connection->timeout.tv_usec;
		FD_ZERO(&fds);
		FD_SET(connection->sock,&fds);
		if((err = select(connection->sock+1,&fds,NULL,NULL,&tv)) == 1) {
			int readed;
			readed = recv(connection->sock,
				&(connection->buffer[connection->buflen]),
				MPD_BUFFER_MAX_LENGTH-connection->buflen,0);
			if(readed<=0) {
				snprintf(connection->errorStr,MPD_BUFFER_MAX_LENGTH,
					"problems getting a response from"
					" \"%s\" on port %i",host,
					port);
				connection->error = MPD_ERROR_NORESPONSE;
				return connection;
			}
			connection->buflen+=readed;
			connection->buffer[connection->buflen] = '\0';
			tv.tv_sec = connection->timeout.tv_sec;
			tv.tv_usec = connection->timeout.tv_usec;
		}
		else if(err<0) {
			switch(errno) {
			case EINTR:
				continue;
			default:
				snprintf(connection->errorStr,
					MPD_BUFFER_MAX_LENGTH,
					"problems connecting to \"%s\" on port"
				 	" %i",host,port);
				connection->error = MPD_ERROR_CONNPORT;
				return connection;
			}
		}
		else {
			snprintf(connection->errorStr,MPD_BUFFER_MAX_LENGTH,
				"timeout in attempting to get a response from"
				 " \"%s\" on port %i",host,port);
			connection->error = MPD_ERROR_NORESPONSE;
			return connection;
		}
	}

	*rt = '\0';
	output = strdup(connection->buffer);
	strcpy(connection->buffer,rt+1);
	connection->buflen = strlen(connection->buffer);

	if(strncmp(output,MPD_WELCOME_MESSAGE,strlen(MPD_WELCOME_MESSAGE))) {
		free(output);
		snprintf(connection->errorStr,MPD_BUFFER_MAX_LENGTH,
				"mpd not running on port %i on host \"%s\"",
				port,host);
		connection->error = MPD_ERROR_NOTMPD;
		return connection;
	}

	{
		char * test;
		char * version[3];
		char * tmp = &output[strlen(MPD_WELCOME_MESSAGE)];
		char * search = ".";
		int i;

		for(i=0;i<3;i++) {
			char * tok;
			if(i==3) search = " ";
			version[i] = strtok_r(tmp,search,&tok);
			if(!version[i]) {
				free(output);
				snprintf(connection->errorStr,
					MPD_BUFFER_MAX_LENGTH,
					"error parsing version number at "
					"\"%s\"",
					&output[strlen(MPD_WELCOME_MESSAGE)]);
				connection->error = MPD_ERROR_NOTMPD;
				return connection;
			}
			connection->version[i] = strtol(version[i],&test,10);
			if(version[i]==test || *test!='\0') {
				free(output);
				snprintf(connection->errorStr,
					MPD_BUFFER_MAX_LENGTH,
					"error parsing version number at "
					"\"%s\"",
					&output[strlen(MPD_WELCOME_MESSAGE)]);
				connection->error = MPD_ERROR_NOTMPD;
				return connection;
			}
			tmp = NULL;
		}
	}

	free(output);

	connection->doneProcessing = 1;

	return connection;
}