Beispiel #1
0
/**
 * \internal Obsługuje pakiet przerwania żądania połączenia bezpośredniego.
 *
 * \param sess Struktura sesji
 * \param e Struktura zdarzenia
 * \param payload Treść pakietu
 * \param len Długość pakietu
 *
 * \return 0 jeśli się powiodło, -1 w przypadku błędu
 */
int gg_dcc7_handle_abort(struct gg_session *sess, struct gg_event *e, void *payload, int len)
{
	struct gg_dcc7_aborted *p = payload;
	struct gg_dcc7 *dcc;

	gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_handle_abort(%p, %p, %p, %d)\n", sess, e, payload, len);

	if (!(dcc = gg_dcc7_session_find(sess, p->id, gg_fix32(0)))) {
		gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_abort() unknown dcc session\n");
		return 0;
	}

	gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_abort() state %d\n", dcc->state);

	if (dcc->state != GG_STATE_IDLE) {
		gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_abort() invalid state\n");
		e->type = GG_EVENT_DCC7_ERROR;
		e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
		e->event.dcc7_error_ex.dcc7 = dcc;
		return 0;
	}

	e->type = GG_EVENT_DCC7_REJECT;
	e->event.dcc7_reject.dcc7 = dcc;
	e->event.dcc7_reject.reason = gg_fix32(GG_DCC7_REJECT_USER);

	// XXX ustawić state na rejected?

	return 0;
}
Beispiel #2
0
/**
 * \internal Obsługuje pakiet akceptacji połączenia bezpośredniego.
 *
 * \param sess Struktura sesji
 * \param e Struktura zdarzenia
 * \param payload Treść pakietu
 * \param len Długość pakietu
 *
 * \return 0 jeśli się powiodło, -1 w przypadku błędu
 */
int gg_dcc7_handle_accept(struct gg_session *sess, struct gg_event *e, void *payload, int len)
{
	struct gg_dcc7_accept *p = payload;
	struct gg_dcc7 *dcc;

	gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_handle_accept(%p, %p, %p, %d)\n", sess, e, payload, len);

	if (!(dcc = gg_dcc7_session_find(sess, p->id, gg_fix32(p->uin)))) {
		gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_accept() unknown dcc session\n");
		// XXX wysłać reject?
		e->type = GG_EVENT_DCC7_ERROR;
		e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
		e->event.dcc7_error_ex.dcc7 = dcc;
		return 0;
	}

	if (dcc->state != GG_STATE_WAITING_FOR_ACCEPT) {
		gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_accept() invalid state\n");
		e->type = GG_EVENT_DCC7_ERROR;
		e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
		e->event.dcc7_error_ex.dcc7 = dcc;
		return 0;
	}
	
	// XXX czy dla odwrotnego połączenia powinniśmy wywołać już zdarzenie GG_DCC7_ACCEPT?
	
	dcc->offset = gg_fix32(p->offset);
	dcc->state = GG_STATE_WAITING_FOR_INFO;

	return 0;
}
Beispiel #3
0
/**
 * \internal Obsługuje pakiet odrzucenia połączenia bezpośredniego.
 *
 * \param sess Struktura sesji
 * \param e Struktura zdarzenia
 * \param payload Treść pakietu
 * \param len Długość pakietu
 *
 * \return 0 jeśli się powiodło, -1 w przypadku błędu
 */
int gg_dcc7_handle_reject(struct gg_session *sess, struct gg_event *e, const void *payload, int len)
{
	const struct gg_dcc7_reject *p = payload;
	struct gg_dcc7 *dcc;

	gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_handle_reject(%p, %p, %p, %d)\n", sess, e, payload, len);

	if (!(dcc = gg_dcc7_session_find(sess, p->id, gg_fix32(p->uin)))) {
		gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_reject() unknown dcc session\n");
		return 0;
	}
	
	if (dcc->state != GG_STATE_WAITING_FOR_ACCEPT) {
		gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_reject() invalid state\n");
		e->type = GG_EVENT_DCC7_ERROR;
		e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
		return 0;
	}

	e->type = GG_EVENT_DCC7_REJECT;
	e->event.dcc7_reject.dcc7 = dcc;
	e->event.dcc7_reject.reason = gg_fix32(p->reason);

	// XXX ustawić state na rejected?

	return 0;
}
Beispiel #4
0
/**
 * \internal Obsługuje pakiet informacji o połączeniu bezpośrednim.
 *
 * \param sess Struktura sesji
 * \param e Struktura zdarzenia
 * \param payload Treść pakietu
 * \param len Długość pakietu
 *
 * \return 0 jeśli się powiodło, -1 w przypadku błędu
 */
int gg_dcc7_handle_info(struct gg_session *sess, struct gg_event *e, void *payload, int len)
{
	struct gg_dcc7_info *p = payload;
	struct gg_dcc7 *dcc;
	char *tmp;

	gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_handle_info(%p, %p, %p, %d)\n", sess, e, payload, len);
	gg_debug_session(sess, GG_DEBUG_FUNCTION, "// gg_dcc7_handle_info() received address: %s, hash: %s\n", p->info, p->hash);

	if (!(dcc = gg_dcc7_session_find(sess, p->id, gg_fix32(p->uin)))) {
		gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() unknown dcc session\n");
		return 0;
	}
	
	if (dcc->state == GG_STATE_CONNECTED) {
		gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() state is already connected\n");
		return 0;
	}

	switch (p->type)
	{
	case GG_DCC7_TYPE_P2P:
		if ((dcc->remote_addr = inet_addr(p->info)) == INADDR_NONE) {
			gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() invalid IP address\n");
			e->type = GG_EVENT_DCC7_ERROR;
			e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
			e->event.dcc7_error_ex.dcc7 = dcc;
			return 0;
		}

		if (!(tmp = strchr(p->info, ' ')) || !(dcc->remote_port = atoi(tmp + 1))) {
			gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() invalid IP port\n");
			e->type = GG_EVENT_DCC7_ERROR;
			e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
			e->event.dcc7_error_ex.dcc7 = dcc;
			return 0;
		}

		if (dcc->state == GG_STATE_WAITING_FOR_INFO) {
			gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() wainting for info so send one\n");
			gg_dcc7_listen_and_send_info(dcc);
			return 0;
		}

		break;

	case GG_DCC7_TYPE_SERVER:
		if (!(tmp = strstr(p->info, "GG"))) {
			gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() unknown info packet\n");
			e->type = GG_EVENT_DCC7_ERROR;
			e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
			e->event.dcc7_error_ex.dcc7 = dcc;
			return 0;
		}

#if defined(GG_CONFIG_HAVE_UINT64_T) && defined(GG_CONFIG_HAVE_STRTOULL)
		{
			uint64_t cid;

			cid = strtoull(tmp + 2, NULL, 0);

			gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() info.str=%s, info.id=%llu, sess.id=%llu\n", tmp + 2, cid, *((unsigned long long*) &dcc->cid));

			cid = gg_fix64(cid);

			if (memcmp(&dcc->cid, &cid, sizeof(cid)) != 0) {
				gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() invalid session id\n");
				e->type = GG_EVENT_DCC7_ERROR;
				e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
				e->event.dcc7_error_ex.dcc7 = dcc;
				return 0;
			}
		}
#endif

		if (gg_dcc7_get_relay_addr(dcc) == -1) {
			gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() unable to retrieve relay address\n");
			e->type = GG_EVENT_DCC7_ERROR;
			e->event.dcc7_error = GG_ERROR_DCC7_RELAY;
			e->event.dcc7_error_ex.dcc7 = dcc;
			return 0;
		}

		// XXX wysyłać dopiero jeśli uda się połączyć z serwerem?

		gg_send_packet(dcc->sess, GG_DCC7_INFO, payload, len, NULL);

		break;

	default:
		gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() unhandled transfer type (%d)\n", p->type);
		e->type = GG_EVENT_DCC7_ERROR;
		e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
		e->event.dcc7_error_ex.dcc7 = dcc;
		return 0;
	}

	// jeśli nadal czekamy na połączenie przychodzące, a druga strona nie
	// daje rady i oferuje namiary na siebie, bierzemy co dają.

// 	if (dcc->state != GG_STATE_WAITING_FOR_INFO && (dcc->state != GG_STATE_LISTENING || dcc->reverse)) {
// 		gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() invalid state\n");
// 		e->type = GG_EVENT_DCC7_ERROR;
// 		e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
//		e->event.dcc7_error_ex.dcc7 = dcc;
// 		return 0;
// 	}

	if (dcc->state == GG_STATE_LISTENING) {
		gg_sock_close(dcc->fd);
		dcc->fd = -1;
		dcc->reverse = 1;
	}
	
	if (dcc->type == GG_SESSION_DCC7_SEND) {
		e->type = GG_EVENT_DCC7_ACCEPT;
		e->event.dcc7_accept.dcc7 = dcc;
		e->event.dcc7_accept.type = gg_fix32(p->type);
		e->event.dcc7_accept.remote_ip = dcc->remote_addr;
		e->event.dcc7_accept.remote_port = dcc->remote_port;
	} else {
		e->type = GG_EVENT_DCC7_PENDING;
		e->event.dcc7_pending.dcc7 = dcc;
	}

	if (dcc->state == GG_STATE_RESOLVING_RELAY)
		return 0;

	if (gg_dcc7_connect(dcc) == -1) {
		if (gg_dcc7_reverse_connect(dcc) == -1) {
			e->type = GG_EVENT_DCC7_ERROR;
			e->event.dcc7_error = GG_ERROR_DCC7_NET;
			e->event.dcc7_error_ex.dcc7 = dcc;
			return 0;
		}
	}

	return 0;
}
Beispiel #5
0
/**
 * \internal Obsługuje pakiet informacji o połączeniu bezpośrednim.
 *
 * \param sess Struktura sesji
 * \param e Struktura zdarzenia
 * \param payload Treść pakietu
 * \param len Długość pakietu
 *
 * \return 0 jeśli się powiodło, -1 w przypadku błędu
 */
int gg_dcc7_handle_info(struct gg_session *sess, struct gg_event *e, void *payload, int len)
{
	struct gg_dcc7_info *p = payload;
	struct gg_dcc7 *dcc;
	char *tmp;

	gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_handle_info(%p, %p, %p, %d)\n", sess, e, payload, len);

	if (!(dcc = gg_dcc7_session_find(sess, p->id, gg_fix32(p->uin)))) {
		gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() unknown dcc session\n");
		return 0;
	}
	
	if (p->type != GG_DCC7_TYPE_P2P) {
		gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() unhandled transfer type (%d)\n", p->type);
		e->type = GG_EVENT_DCC7_ERROR;
		e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
		return 0;
	}

	if ((dcc->remote_addr = inet_addr(p->info)) == INADDR_NONE) {
		gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() invalid IP address\n");
		e->type = GG_EVENT_DCC7_ERROR;
		e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
		return 0;
	}

	if (!(tmp = strchr(p->info, ' ')) || !(dcc->remote_port = atoi(tmp + 1))) {
		gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() invalid IP port\n");
		e->type = GG_EVENT_DCC7_ERROR;
		e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
		return 0;
	}

	// jeśli nadal czekamy na połączenie przychodzące, a druga strona nie
	// daje rady i oferuje namiary na siebie, bierzemy co dają.

	if (dcc->state != GG_STATE_WAITING_FOR_INFO && (dcc->state != GG_STATE_LISTENING || dcc->reverse)) {
		gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() invalid state\n");
		e->type = GG_EVENT_DCC7_ERROR;
		e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
		return 0;
	}

	if (dcc->state == GG_STATE_LISTENING) {
		close(dcc->fd);
		dcc->fd = -1;
		dcc->reverse = 1;
	}
	
	if (dcc->type == GG_SESSION_DCC7_SEND) {
		e->type = GG_EVENT_DCC7_ACCEPT;
		e->event.dcc7_accept.dcc7 = dcc;
		e->event.dcc7_accept.type = gg_fix32(p->type);
		e->event.dcc7_accept.remote_ip = dcc->remote_addr;
		e->event.dcc7_accept.remote_port = dcc->remote_port;
	} else {
		e->type = GG_EVENT_DCC7_PENDING;
	}

	if (gg_dcc7_connect(sess, dcc) == -1) {
		if (gg_dcc7_reverse_connect(dcc) == -1) {
			e->type = GG_EVENT_DCC7_ERROR;
			e->event.dcc7_error = GG_ERROR_DCC7_NET;
			return 0;
		}
	}

	return 0;
}