示例#1
0
int tcpclient_sendall(tcpclient_t *client, const char *buf, size_t len) {
	buffer_t *sendq = &client->send_queue;

	if (client->addr == NULL) {
		stats_error_log("tcpclient[%s]: Cannot send before connect!", client->name);
		return 1;
	} else {
		// Does nothing if we're already connected, triggers a
		// reconnect if backoff has expired.
		tcpclient_connect(client);
	}

	if (buffer_datacount(&client->send_queue) >= client->config->max_send_queue) {
		if (client->failing == 0) {
			stats_error_log("tcpclient[%s]: send queue for %s client is full (at %zd bytes, max is %" PRIu64 " bytes), dropping data",
					client->name,
					tcpclient_state_name[client->state],
					buffer_datacount(&client->send_queue),
					client->config->max_send_queue);
			client->failing = 1;
		}
		return 2;
	}
	if (buffer_spacecount(sendq) < len) {
		if (buffer_realign(sendq) != 0) {
			stats_error_log("tcpclient[%s]: Unable to realign send queue", client->name);
			return 3;
		}
	}
	while (buffer_spacecount(sendq) < len) {
		if (buffer_expand(sendq) != 0) {
			stats_error_log("tcpclient[%s]: Unable to allocate additional memory for send queue, dropping data", client->name);
			return 4;
		}
	}
	memcpy(buffer_tail(sendq), buf, len);
	buffer_produced(sendq, len);

	if (client->state == STATE_CONNECTED) {
		client->write_watcher.started = true;
		ev_io_start(client->loop, &client->write_watcher.watcher);
	}
	return 0;
}
示例#2
0
//-----------------------------------------------------------------------------
NetworkType* new_tcp_client_state(
	char* ip, 
	int port, 
	uint32_t *ticks)
{
	NetworkType *tcp = malloc(sizeof(NetworkType));
	tcp->tick = tick;
	tcp->logic_tick = logic_tick;
	tcp->add_command = add_command;
	tcp->get_command = get_command;
	tcp->get_id = get_id;
	tcp->cleanup = cleanup;

	TcpClientState *state = (TcpClientState *) malloc(sizeof(TcpClientState));
	memset(state, 0, sizeof(TcpClientState));
	tcp->state = (void *)state;

	state->msg_size = 0;
	state->in = new_queue(1);	
	state->out = new_queue(1);
	state->last_post_time = 0;	
	state->post_delay = 0.12;
	state->waiting = 0;
	state->client_id = -1;
	state->ready = 0;
	state->read_buf = malloc(1);
	state->ticks = ticks;

	state->socket = new_tcpclient();
	tcpclient_init(state->socket, port, ip);
	tcpclient_set_user_data(state->socket, tcp->state);

	printf("Connecting...\n");
	tcpclient_set_handlers(state->socket, &client_read, &client_disconnect);
	tcpclient_connect(state->socket);
		
	return tcp;
}
示例#3
0
	/* parsing lists {{{*/
	if(service)
	{
		xmlNodePtr memberships = findNode(service->children, "Memberships", 1);
		xmlNodePtr ms;
		xmlNodePtr role;
		xmlNodePtr members, member;
		xmlNodePtr pname;
		xmlNodePtr type;
		xmlNodePtr lastchange;
		xmlChar *content;
		int flag = 0;
		lastchange = findNode(service->children, "LastChange", 1);
		content = xmlNodeGetContent(lastchange);
		cl->lastchange = strdup((char*)content);
		DMSG(stderr, "Contact: lastchange = %s\n", cl->lastchange);
		if(!memberships)
		{
			fprintf(stderr, "NULL membership\n");
			count = 0;
			goto cleanup;
		}
		for(ms=memberships->children;ms;ms=ms->next)
		{
			int ctype = 1;
			if(!ms->children) continue;
			role = findNode(ms->children, "MemberRole", 1);
			if(!role)
			{
				fprintf(stderr, "Null role\n");
				count = 0;
				goto cleanup;
			}
			members = findNode(role, "Members", 1);
			if(!members) continue;

			if(xmlStrEqual(role->children->content, (xmlChar*)"Allow"))
				flag = 3;
			else if(xmlStrEqual(role->children->content, (xmlChar*)"Block"))
				flag = 4;
			else
				continue;

			for(member=members->children;member;member=member->next)
			{
				Contact *c;
				type = findNode(member->children, "Type", 1);
				content = xmlNodeGetContent(type);
				if(!content)
				{
					fprintf(stderr, "NULL Type\n");
					continue;
				}
				if(xmlStrEqual(content, (xmlChar*)"Passport"))
				{
					pname = findNode(member->children, "PassportName", 1);
					ctype = 1;
				}
				else if(xmlStrEqual(content, (xmlChar*)"Email"))
				{
					pname = findNode(member->children, "Email", 1);
					ctype = 32;
				}
				else
					continue;

				xmlFree(content);
				if(!pname) 
				{
					fprintf(stderr, "NULL PassportName or Email\n");
					continue;
				}
				content = xmlNodeGetContent(pname);
				if(content)
				{
					char name[32];
					char domain[32];
					if(sscanf((char*)content, "%[^@]@%s", name, domain) != 2)
					{
						fprintf(stderr, "parse contact: malformed email: %s\n", content);
						continue;
					}
					c = contact_new((char*)content);
					c->name = strdup(name);
					c->type = ctype;
					c->status = NA;
					c->inlist |= flag;
					c->domain = NULL; /* should be filled during sort */
					cl_append_contact(cl, c, name, domain);
					xmlFree(content);
					count++;
				}
			}
		}
	}/*}}}*/
	DMSG(stderr, "parsed contact count: %d\n", count);

cleanup:
	cl->flag &= ~CL_INITLIST;
	return count;

}/*}}}*/
int _cl_do_soapreq_ab(CL *cl)/*{{{*/
{
	TCPClient *client;
	char *req = NULL;
	char *header;
	char buf[512];
	int ret, len;
	char *ptr = NULL;
	client = tcpclient_new("contacts.msn.com", 80);
	ret = _cl_load_soapreq_ab(cl, cl->ablastchange, &req, TRUE);
	if(ret)
	{
		tcpclient_connect(client);
		header = (char*)xmalloc(strlen(ab_request_header) + 32);
		DMSG(stderr, "sending ab request\n");
		len = sprintf(header, "%s%d\r\n\r\n", ab_request_header, ret);
		if(tcpclient_send(client, header, len) <= 0) goto cleanup;
		if(tcpclient_send(client, req, ret) <= 0) goto cleanup;

		len = tcpclient_recv_header(client, &ptr); /* header */
		if(ptr)
		{
			HTTPHeader *header;
			xmlDocPtr doc;
			xmlParserCtxtPtr ctxt;
			FILE *fp;

			DMSG(stderr, "AB response header:\n%s", ptr);
			header = http_parse_header(ptr);
			len = header->content_length;
			DMSG(stderr, "Length: %d\n", len);
			http_header_destroy(header);
			memset(buf, 0, sizeof(buf));
			fp = fopen("addressbook.xml", "w");
			fprintf(fp, buf);
			len -= (ret = tcpclient_recv(client, buf, sizeof(buf)-1));
			ctxt = xmlCreatePushParserCtxt(NULL, NULL, buf, ret, "addressbook.xml");
			fprintf(fp, buf);
			if(ctxt == NULL)
			{
				fprintf(stderr, "failed to create parser context");
				return 0;
			}

			while(len > 0)
			{
				memset(buf, 0, sizeof(buf));
				len -= (ret=tcpclient_recv(client, buf, sizeof(buf)-1));
				fprintf(fp, buf);
				xmlParseChunk(ctxt, buf, ret, 0);
			}
			fclose(fp);
			xmlParseChunk(ctxt, buf, 0, 1);
			tcpclient_destroy(client);
			client = NULL;
			doc = ctxt->myDoc;
			len = ctxt->wellFormed;
			xmlFreeParserCtxt(ctxt);
			//count += _cl_parse_contacts(cl, doc);
			xmlFreeDoc(doc);
			xmlCleanupParser();
			DMSG(stderr, "addressbook xml parsing done: %s\n", len?"good":"malformed");
			xfree(ptr);
		}
		else
		{
			DMSG(stderr, "ab: no header found\n\r");
		}
	}
	else
	{
		fprintf(stderr, "failed to load abreq\n");
	}
cleanup:
	xfree(header);
	return 0;
}/*}}}*/
示例#4
0
int tcpclient_connect(tcpclient_t *client) {
	struct addrinfo hints;
	struct addrinfo *addr;
	int sd;

	if (client->state == STATE_CONNECTED || client->state == STATE_CONNECTING) {
		// Already connected, do nothing
		return 1;
	}

	if (client->state == STATE_BACKOFF) {
		// If backoff timer has expired, change to STATE_INIT and call recursively
		if ((time(NULL) - client->last_error) > TCPCLIENT_RETRY_TIMEOUT) {
			tcpclient_set_state(client, STATE_INIT);
			return tcpclient_connect(client);
		} else {
			return 2;
		}
	}

	if (client->state == STATE_INIT) {
		// Resolve address, create socket, set nonblocking, setup callbacks, fire connect
		if (client->config->always_resolve_dns == true && client->addr != NULL) {
			freeaddrinfo(client->addr);
			client->addr = NULL;
		}

		if (client->addr == NULL) {
			// We only know about tcp and udp, so if we get something unexpected just
			// default to tcp
			if (strncmp(client->protocol, "udp", 3) == 0) {
				client->socktype = SOCK_DGRAM;
			} else {
				client->socktype = SOCK_STREAM;
			}
			memset(&hints, 0, sizeof(hints));
			hints.ai_family = AF_UNSPEC;
			hints.ai_socktype = client->socktype;
			hints.ai_flags = AI_PASSIVE;

			if (getaddrinfo(client->host, client->port, &hints, &addr) != 0) {
				stats_error_log("tcpclient: Error resolving backend address %s: %s", client->host, gai_strerror(errno));
				client->last_error = time(NULL);
				tcpclient_set_state(client, STATE_BACKOFF);
				client->callback_error(client, EVENT_ERROR, client->callback_context, NULL, 0);
				return 3;
			}
			client->addr = addr;
			snprintf(client->name, TCPCLIENT_NAME_LEN, "%s/%s/%s", client->host, client->port, client->protocol);
		} else {
			addr = client->addr;
		}

		if ((sd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol)) < 0) {
			stats_error_log("tcpclient[%s]: Unable to create socket: %s", client->name, strerror(errno));
			client->last_error = time(NULL);
			tcpclient_set_state(client, STATE_BACKOFF);
			client->callback_error(client, EVENT_ERROR, client->callback_context, NULL, 0);
			return 4;
		}
#ifdef TCP_CORK
		if (client->config->enable_tcp_cork &&
		    addr->ai_family == AF_INET &&
		    addr->ai_socktype == SOCK_STREAM &&
		    addr->ai_protocol == IPPROTO_TCP) {
			int state = 1;
			if (setsockopt(sd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state))) {
				stats_error_log("failed to set TCP_CORK");
			}
		}
#endif
		client->sd = sd;

		if (fcntl(sd, F_SETFL, (fcntl(sd, F_GETFL) | O_NONBLOCK)) != 0) {
			stats_error_log("tcpclient[%s]: Unable to set socket to non-blocking: %s", client->name, strerror(errno));
			client->last_error = time(NULL);
			tcpclient_set_state(client, STATE_BACKOFF);
			close(sd);
			client->callback_error(client, EVENT_ERROR, client->callback_context, NULL, 0);
			return 5;
		}

		client->connect_watcher.started = true;
		client->connect_watcher.watcher.data = client;
		client->timeout_watcher.data = client;
		ev_io_init(&client->connect_watcher.watcher, tcpclient_connected, sd, EV_WRITE);
		ev_io_start(client->loop, &client->connect_watcher.watcher);
		ev_timer_set(&client->timeout_watcher, TCPCLIENT_CONNECT_TIMEOUT, 0);
		ev_timer_start(client->loop, &client->timeout_watcher);

		if (connect(sd, addr->ai_addr, addr->ai_addrlen) != 0 && errno != EINPROGRESS) {
			stats_error_log("tcpclient[%s]: Unable to connect: %s", client->name, strerror(errno));
			client->last_error = time(NULL);
			tcpclient_set_state(client, STATE_BACKOFF);
			ev_timer_stop(client->loop, &client->timeout_watcher);
			ev_io_stop(client->loop, &client->connect_watcher.watcher);
			close(sd);
			client->callback_error(client, EVENT_ERROR, client->callback_context, NULL, 0);
			return 6;
		}

		tcpclient_set_state(client, STATE_CONNECTING);
		return 0;
	}

	stats_error_log("tcpclient[%s]: Connect with unknown state %i", client->name, client->state);
	return 7;
}