예제 #1
0
파일: files.cpp 프로젝트: kxepal/miranda-ng
/** an incoming file transfer has been offered */
void mwFileTransfer_offered(mwFileTransfer* ft)
{
	CSametimeProto* proto = getProtoFromMwFileTransfer(ft);
	proto->debugLog(_T("mwFileTransfer_offered() start"));

	const mwIdBlock* idb = mwFileTransfer_getUser(ft);
	MCONTACT hContact = proto->FindContactByUserId(idb->user);
	proto->debugLog(_T("Sametime mwFileTransfer_offered hContact=[%x]"), hContact);

	if (!hContact) {
		mwSametimeList* user_list = mwSametimeList_new();
		mwSametimeGroup* stgroup = mwSametimeGroup_new(user_list, mwSametimeGroup_NORMAL, Translate("None"));
		mwSametimeUser* stuser = mwSametimeUser_new(stgroup, mwSametimeUser_NORMAL, (mwIdBlock*)idb);
		hContact = proto->AddContact(stuser, (proto->options.add_contacts ? false : true));
	}

	proto->ProtoBroadcastAck(hContact, ACKTYPE_FILE, ACKRESULT_INITIALISING, (HANDLE)ft, 0);

	TCHAR* filenameT = mir_utf8decodeT(mwFileTransfer_getFileName(ft));
	const char* message = mwFileTransfer_getMessage(ft);
	TCHAR descriptionT[512];
	if (message) {
		TCHAR* messageT = mir_utf8decodeT(message);
		mir_sntprintf(descriptionT, _T("%s - %s"), filenameT, messageT);
		mir_free(messageT);
	} else
		_tcsncpy_s(descriptionT, filenameT, _TRUNCATE);

	PROTORECVFILET pre = {0};
	pre.dwFlags = PRFF_TCHAR;
	pre.fileCount = 1;
	pre.timestamp = time(NULL);
	pre.descr.t = descriptionT;
	pre.files.t = &filenameT;
	pre.lParam = (LPARAM)ft;

	ProtoChainRecvFile(hContact, &pre);
	
	mir_free(filenameT);
}
예제 #2
0
void __cdecl GGPROTO::dccmainthread(void*)
{
	uin_t uin;
	gg_event *e;
	struct timeval tv;
	fd_set rd, wd;
	int ret;
	SOCKET maxfd;
	DWORD tick;
	list_t l;
	char szFilename[MAX_PATH];

	// Zero up lists
	watches = transfers = requests = l = NULL;

	debugLogA("dccmainthread(): started. DCC Server Thread Starting");

	// Readup number
	if (!(uin = getDword(GG_KEY_UIN, 0)))
	{
		debugLogA("dccmainthread(): No Gadu-Gadu number specified. Exiting.");
		if (hEvent) SetEvent(hEvent);
#ifdef DEBUGMODE
		debugLogA("dccmainthread(): end 1.");
#endif
		return;
	}

	// Create listen socket on config direct port
	if (!(dcc = gg_dcc_socket_create(uin, (uint16_t)getWord(GG_KEY_DIRECTPORT, GG_KEYDEF_DIRECTPORT))))
	{
		debugLogA("dccmainthread(): Cannot create DCC listen socket. Exiting.");
		// Signalize mainthread we haven't start
		if (hEvent) SetEvent(hEvent);
#ifdef DEBUGMODE
		debugLogA("dccmainthread(): end 2.");
#endif
		return;
	}

	gg_dcc_port = dcc->port;
	gg_dcc_ip = inet_addr("255.255.255.255");
	debugLogA("dccmainthread(): Listening on port %d.", gg_dcc_port);

	// Signalize mainthread we started
	if (hEvent) SetEvent(hEvent);

	// Add main dcc handler to watches
	list_add(&watches, dcc, 0);

	// Do while we are in the main server thread
	while(pth_dcc.dwThreadId && dcc)
	{
		// Timeouts
		tv.tv_sec = 1;
		tv.tv_usec = 0;

		// Prepare descriptiors for select
		FD_ZERO(&rd);
		FD_ZERO(&wd);

		for (maxfd = 0, l = watches; l; l = l->next)
		{
			gg_common *w = (gg_common*)l->data;

			if (!w || w->state == GG_STATE_ERROR || w->state == GG_STATE_IDLE || w->state == GG_STATE_DONE)
				continue;

			// Check if it's proper descriptor
			if (w->fd == -1) continue;

			if (w->fd > maxfd)
				maxfd = w->fd;
			if ((w->check & GG_CHECK_READ))
				FD_SET(w->fd, &rd);
			if ((w->check & GG_CHECK_WRITE))
				FD_SET(w->fd, &wd);
		}

		// Wait for data on selects
		ret = select(maxfd + 1, &rd, &wd, NULL, &tv);

		// Check for select error
		if (ret == -1)
		{
			if (errno == EBADF)
				debugLogA("dccmainthread(): Bad descriptor on select().");
			else if (errno != EINTR)
				debugLogA("dccmainthread(): Unknown error on select().");
			continue;
		}

		// Process watches (carefull with l)
		l = watches;
		gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1);
		while (l)
		{
			struct gg_common *local_c = (gg_common*)l->data;
			struct gg_dcc *local_dcc = (gg_dcc*)l->data;
			struct gg_dcc7 *local_dcc7 = (gg_dcc7*)l->data;
			l = l->next;

			switch (local_c->type)
			{
				default:
					if (!local_dcc || (!FD_ISSET(local_dcc->fd, &rd) && !FD_ISSET(local_dcc->fd, &wd)))
						continue;

					/////////////////////////////////////////////////////////////////
					// Process DCC events

					// Connection broken/closed
					gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 2, "ft_mutex", 1);
					if (!(e = gg_dcc_socket_watch_fd(local_dcc)))
					{
						debugLogA("dccmainthread(): Socket closed.");
						// Remove socket and _close
						gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1);
						list_remove(&watches, local_dcc, 0);
						gg_dcc_socket_free(local_dcc);

						// Check if it's main socket
						if (local_dcc == dcc) dcc = NULL;
						continue;
					} else {
						gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1);
						debugLogA("dccmainthread(): Event: %s", ggdebug_eventtype(e));
					}

					switch(e->type)
					{
						// Client connected
						case GG_EVENT_DCC_NEW:
							list_add(&watches, e->event.dcc_new, 0);
							e->event.dcc_new = NULL;
							break;

						//
						case GG_EVENT_NONE:
							// If transfer in progress do status
							if (local_dcc->file_fd != -1 && local_dcc->offset > 0 && (((tick = GetTickCount()) - local_dcc->tick) > GGSTATREFRESHEVERY))
							{
								PROTOFILETRANSFERSTATUS pfts;
								local_dcc->tick = tick;
								mir_snprintf(szFilename, "%s%s", local_dcc->folder, local_dcc->file_info.filename);
								memset(&pfts, 0, sizeof(PROTOFILETRANSFERSTATUS));
								pfts.cbSize = sizeof(PROTOFILETRANSFERSTATUS);
								pfts.hContact = (UINT_PTR)local_dcc->contact;
								pfts.flags = (local_dcc->type == GG_SESSION_DCC_SEND);
								pfts.pszFiles = NULL;
								pfts.totalFiles = 1;
								pfts.currentFileNumber = 0;
								pfts.totalBytes = local_dcc->file_info.size;
								pfts.totalProgress = local_dcc->offset;
								pfts.szWorkingDir = local_dcc->folder;
								pfts.szCurrentFile = szFilename;
								pfts.currentFileSize = local_dcc->file_info.size;
								pfts.currentFileProgress = local_dcc->offset;
								pfts.currentFileTime = 0;
								gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 3, "ft_mutex", 1);
								ProtoBroadcastAck((UINT_PTR)local_dcc->contact, ACKTYPE_FILE, ACKRESULT_DATA, local_dcc, (LPARAM)&pfts);
								gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1);
							}
							break;

						// Connection was successfuly ended
						case GG_EVENT_DCC_DONE:
							debugLogA("dccmainthread(): Client: %d, Transfer done ! Closing connection.", dcc->peer_uin);
							// Remove from watches
							list_remove(&watches, local_dcc, 0);
							// Close file & success
							if (local_dcc->file_fd != -1)
							{
								PROTOFILETRANSFERSTATUS pfts;
								mir_snprintf(szFilename, "%s%s", local_dcc->folder, local_dcc->file_info.filename);
								memset(&pfts, 0, sizeof(PROTOFILETRANSFERSTATUS));
								pfts.cbSize = sizeof(PROTOFILETRANSFERSTATUS);
								pfts.hContact = (UINT_PTR)local_dcc->contact;
								pfts.flags = (local_dcc->type == GG_SESSION_DCC_SEND);
								pfts.pszFiles = NULL;
								pfts.totalFiles = 1;
								pfts.currentFileNumber = 0;
								pfts.totalBytes = local_dcc->file_info.size;
								pfts.totalProgress = local_dcc->file_info.size;
								pfts.szWorkingDir = local_dcc->folder;
								pfts.szCurrentFile = szFilename;
								pfts.currentFileSize = local_dcc->file_info.size;
								pfts.currentFileProgress = local_dcc->file_info.size;
								pfts.currentFileTime = 0;
								gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 4, "ft_mutex", 1);
								ProtoBroadcastAck((UINT_PTR)local_dcc->contact, ACKTYPE_FILE, ACKRESULT_DATA, local_dcc, (LPARAM)&pfts);
								gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1);
								_close(local_dcc->file_fd); local_dcc->file_fd = -1;
								gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 5, "ft_mutex", 1);
								ProtoBroadcastAck((UINT_PTR)local_dcc->contact, ACKTYPE_FILE, ACKRESULT_SUCCESS, local_dcc, 0);
								gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1);
							}
							// Free dcc
							gg_free_dcc(local_dcc); if (local_dcc == dcc) dcc = NULL;
							break;

						// Client error
						case GG_EVENT_DCC_ERROR:
							switch (e->event.dcc_error)
							{
								case GG_ERROR_DCC_HANDSHAKE:
									debugLogA("dccmainthread(): Client: %d, Handshake error.", local_dcc->peer_uin);
									break;
								case GG_ERROR_DCC_NET:
									debugLogA("dccmainthread(): Client: %d, Network error.", local_dcc->peer_uin);
									break;
								case GG_ERROR_DCC_FILE:
									debugLogA("dccmainthread(): Client: %d, File read/write error.", local_dcc->peer_uin);
									break;
								case GG_ERROR_DCC_EOF:
									debugLogA("dccmainthread(): Client: %d, End of file/connection error.", local_dcc->peer_uin);
									break;
								case GG_ERROR_DCC_REFUSED:
									debugLogA("dccmainthread(): Client: %d, Connection refused error.", local_dcc->peer_uin);
									break;
								default:
									debugLogA("dccmainthread(): Client: %d, Unknown error.", local_dcc->peer_uin);
							}
							// Don't do anything if it's main socket
							if (local_dcc == dcc) break;

							// Remove from watches
							list_remove(&watches, local_dcc, 0);

							// Close file & fail
							if (local_dcc->contact)
							{
								_close(local_dcc->file_fd); local_dcc->file_fd = -1;
								gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 6, "ft_mutex", 1);
								ProtoBroadcastAck((UINT_PTR)local_dcc->contact, ACKTYPE_FILE, ACKRESULT_FAILED, local_dcc, 0);
								gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1);
							}
							// Free dcc
							gg_free_dcc(local_dcc); if (local_dcc == dcc) dcc = NULL;
							break;

						// Need file acknowledgement
						case GG_EVENT_DCC_NEED_FILE_ACK:
							debugLogA("dccmainthread(): Client: %d, File ack filename \"%s\" size %d.", local_dcc->peer_uin,
									local_dcc->file_info.filename, local_dcc->file_info.size);
							// Do not watch for transfer until user accept it
							list_remove(&watches, local_dcc, 0);
							// Add to waiting transfers
							list_add(&transfers, local_dcc, 0);

							//////////////////////////////////////////////////
							// Add file recv request
							{
								// Make new ggtransfer struct
								local_dcc->contact = (void*)getcontact(local_dcc->peer_uin, 0, 0, NULL);
								TCHAR* filenameT = mir_utf8decodeT((char*)dcc->file_info.filename);

								PROTORECVFILET pre = {0};
								pre.dwFlags = PRFF_TCHAR;
								pre.fileCount = 1;
								pre.timestamp = time(NULL);
								pre.descr.t = filenameT;
								pre.files.t = &filenameT;
								pre.lParam = (LPARAM)local_dcc;

								gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 7, "ft_mutex", 1);
								ProtoChainRecvFile((UINT_PTR)local_dcc->contact, &pre);
								gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1);

								mir_free(filenameT);
							}
							break;

						// Need client accept
						case GG_EVENT_DCC_CLIENT_ACCEPT:
							debugLogA("dccmainthread(): Client: %d, Client accept.", local_dcc->peer_uin);
							// Check if user is on the list and if it is my uin
							if (getcontact(local_dcc->peer_uin, 0, 0, NULL) &&
								getDword(GG_KEY_UIN, -1) == local_dcc->uin)
								break;

							// Kill unauthorized dcc
							list_remove(&watches, dcc, 0);
							gg_free_dcc(local_dcc); if (local_dcc == dcc) dcc = NULL;
							break;

						// Client connected as we wished to (callback)
						case GG_EVENT_DCC_CALLBACK:
						{
							int found = 0;
							debugLogA("dccmainthread(): Callback from client %d.", local_dcc->peer_uin);
							// Seek for stored callback request
							for (l = requests; l; l = l->next)
							{
								struct gg_dcc *req = (gg_dcc*)l->data;

								if (req && req->peer_uin == local_dcc->peer_uin)
								{
									gg_dcc_set_type(local_dcc, GG_SESSION_DCC_SEND);
									found = 1;

									// Copy data req ===> dcc
									local_dcc->folder = req->folder;
									local_dcc->contact = req->contact;
									local_dcc->file_fd = req->file_fd;
									memcpy(&local_dcc->file_info, &req->file_info, sizeof(struct gg_file_info));
									// Copy data back to dcc ===> req
									memcpy(req, local_dcc, sizeof(struct gg_dcc));

									// Remove request
									list_remove(&requests, req, 0);
									// Remove dcc from watches
									list_remove(&watches, local_dcc, 0);
									// Add request to watches
									list_add(&watches, req, 0);
									// Free old dat
									gg_free_dcc(local_dcc);
									debugLogA("dccmainthread(): Found stored request to client %d, filename \"%s\" size %d, folder \"%s\".",
										req->peer_uin, req->file_info.filename, req->file_info.size, req->folder);
									break;
								}
							}

							if (!found)
							{
								debugLogA("dccmainthread(): Unknown request to client %d.", local_dcc->peer_uin);
								// Kill unauthorized dcc
								list_remove(&watches, local_dcc, 0);
								gg_free_dcc(local_dcc); if (local_dcc == dcc) dcc = NULL;
							}
							break;
						}
					}

					// Free event
					gg_free_event(e);
					break;

				case GG_SESSION_DCC7_SOCKET:
				case GG_SESSION_DCC7_GET:
				case GG_SESSION_DCC7_SEND:
				case GG_SESSION_DCC7_VOICE:
					if (!local_dcc7 || (!FD_ISSET(local_dcc7->fd, &rd) && !FD_ISSET(local_dcc7->fd, &wd)))
						continue;

					/////////////////////////////////////////////////////////////////
					// Process DCC7 events

					// Connection broken/closed
					gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 8, "ft_mutex", 1);
					if (!(e = gg_dcc7_watch_fd(local_dcc7)))
					{
						debugLogA("dccmainthread(): Socket closed.");
						// Remove socket and _close
						gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1);
						list_remove(&watches, local_dcc7, 0);
						gg_dcc7_free(local_dcc7);
						continue;
					} else {
						gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1);
						debugLogA("dccmainthread(): Event: %s", ggdebug_eventtype(e));
					}

					switch(e->type)
					{
						//
						case GG_EVENT_NONE:
							// If transfer in progress do status
							if (local_dcc7->file_fd != -1 && local_dcc7->offset > 0 && (((tick = GetTickCount()) - local_dcc7->tick) > GGSTATREFRESHEVERY))
							{
								PROTOFILETRANSFERSTATUS pfts;
								local_dcc7->tick = tick;
								mir_snprintf(szFilename, "%s%s", local_dcc->folder, local_dcc7->filename);
								memset(&pfts, 0, sizeof(PROTOFILETRANSFERSTATUS));
								pfts.cbSize = sizeof(PROTOFILETRANSFERSTATUS);
								pfts.hContact = (UINT_PTR)local_dcc7->contact;
								pfts.flags = (local_dcc7->type == GG_SESSION_DCC7_SEND);
								pfts.pszFiles = NULL;
								pfts.totalFiles = 1;
								pfts.currentFileNumber = 0;
								pfts.totalBytes = local_dcc7->size;
								pfts.totalProgress = local_dcc7->offset;
								pfts.szWorkingDir = local_dcc7->folder;
								pfts.szCurrentFile = szFilename;
								pfts.currentFileSize = local_dcc7->size;
								pfts.currentFileProgress = local_dcc7->offset;
								pfts.currentFileTime = 0;
								gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 9, "ft_mutex", 1);
								ProtoBroadcastAck((UINT_PTR)local_dcc7->contact, ACKTYPE_FILE, ACKRESULT_DATA, local_dcc7, (LPARAM)&pfts);
								gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1);
							}
							break;

						// Connection was successfuly ended
						case GG_EVENT_DCC7_DONE:
							debugLogA("dccmainthread(): Client: %d, Transfer done ! Closing connection.", dcc->peer_uin);
							// Remove from watches
							list_remove(&watches, local_dcc7, 0);
							// Close file & success
							if (local_dcc7->file_fd != -1)
							{
								PROTOFILETRANSFERSTATUS pfts;
								mir_snprintf(szFilename, "%s%s", local_dcc->folder, local_dcc7->filename);
								memset(&pfts, 0, sizeof(PROTOFILETRANSFERSTATUS));
								pfts.cbSize = sizeof(PROTOFILETRANSFERSTATUS);
								pfts.hContact = (UINT_PTR)local_dcc7->contact;
								pfts.flags = (local_dcc7->type == GG_SESSION_DCC7_SEND);
								pfts.pszFiles = NULL;
								pfts.totalFiles = 1;
								pfts.currentFileNumber = 0;
								pfts.totalBytes = local_dcc7->size;
								pfts.totalProgress = local_dcc7->size;
								pfts.szWorkingDir = local_dcc7->folder;
								pfts.szCurrentFile = szFilename;
								pfts.currentFileSize = local_dcc7->size;
								pfts.currentFileProgress = local_dcc7->size;
								pfts.currentFileTime = 0;
								gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 10, "ft_mutex", 1);
								ProtoBroadcastAck((UINT_PTR)local_dcc7->contact, ACKTYPE_FILE, ACKRESULT_DATA, local_dcc7, (LPARAM)&pfts);
								gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1);
								_close(local_dcc7->file_fd); local_dcc7->file_fd = -1;
								gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 11, "ft_mutex", 1);
								ProtoBroadcastAck((UINT_PTR)local_dcc7->contact, ACKTYPE_FILE, ACKRESULT_SUCCESS, local_dcc7, 0);
								gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1);
							}
							// Free dcc
							gg_dcc7_free(local_dcc7);
							break;

						// Client error
						case GG_EVENT_DCC7_ERROR:
							switch (e->event.dcc7_error)
							{
								case GG_ERROR_DCC7_HANDSHAKE:
									debugLogA("dccmainthread(): Client: %d, Handshake error.", local_dcc7->peer_uin);
									break;
								case GG_ERROR_DCC7_NET:
									debugLogA("dccmainthread(): Client: %d, Network error.", local_dcc7->peer_uin);
									break;
								case GG_ERROR_DCC7_FILE:
									debugLogA("dccmainthread(): Client: %d, File read/write error.", local_dcc7->peer_uin);
									break;
								case GG_ERROR_DCC7_EOF:
									debugLogA("dccmainthread(): Client: %d, End of file/connection error.", local_dcc7->peer_uin);
									break;
								case GG_ERROR_DCC7_REFUSED:
									debugLogA("dccmainthread(): Client: %d, Connection refused error.", local_dcc7->peer_uin);
									break;
								case GG_ERROR_DCC7_RELAY:
									debugLogA("dccmainthread(): Client: %d, Relay connection error.", local_dcc7->peer_uin);
									break;
								default:
									debugLogA("dccmainthread(): Client: %d, Unknown error.", local_dcc7->peer_uin);
							}
							// Remove from watches
							list_remove(&watches, local_dcc7, 0);

							// Close file & fail
							if (local_dcc7->file_fd != -1)
							{
								_close(local_dcc7->file_fd);
								local_dcc7->file_fd = -1;
							}

							if (local_dcc7->contact) {
								gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 12, "ft_mutex", 1);
								ProtoBroadcastAck((UINT_PTR)local_dcc7->contact, ACKTYPE_FILE, ACKRESULT_FAILED, local_dcc7, 0);
								gg_EnterCriticalSection(&ft_mutex, "dccmainthread", 37, "ft_mutex", 1);
							}

							// Free dcc
							gg_dcc7_free(local_dcc7);
							break;
					}

					// Free event
					gg_free_event(e);
					break;
			}
		}
		gg_LeaveCriticalSection(&ft_mutex, "dccmainthread", 37, 1, "ft_mutex", 1);
	}

	// Close all dcc client sockets
	for (l = watches; l; l = l->next)
	{
		struct gg_common *c = (gg_common*)l->data;
		if (!c) continue;
		if (c->type == GG_SESSION_DCC7_SOCKET || c->type == GG_SESSION_DCC7_SEND || c->type == GG_SESSION_DCC7_GET)
		{
			struct gg_dcc7 *local_dcc7 = (gg_dcc7*)l->data;
			gg_dcc7_free(local_dcc7);
		}
		else
		{
			struct gg_dcc *local_dcc = (gg_dcc*)l->data;
			gg_dcc_socket_free(local_dcc);

			// Check if it's main socket
			if (local_dcc == dcc) dcc = NULL;
		}
	}
	// Close all waiting for aknowledgle transfers
	for (l = transfers; l; l = l->next)
	{
		struct gg_common *c = (gg_common*)l->data;
		if (!c) continue;
		if (c->type == GG_SESSION_DCC7_SOCKET || c->type == GG_SESSION_DCC7_SEND || c->type == GG_SESSION_DCC7_GET)
		{
			struct gg_dcc7 *local_dcc7 = (gg_dcc7*)l->data;
			gg_dcc7_free(local_dcc7);
		}
		else
		{
			struct gg_dcc *local_dcc = (gg_dcc*)l->data;
			gg_dcc_socket_free(local_dcc);
		}
	}
	// Close all waiting dcc requests
	for (l = requests; l; l = l->next)
	{
		struct gg_dcc *local_dcc = (gg_dcc*)l->data;
		if (local_dcc) gg_free_dcc(local_dcc);
	}
	list_destroy(watches, 0);
	list_destroy(transfers, 0);
	list_destroy(requests, 0);

	gg_dcc_port = 0;
	gg_dcc_ip = 0;
	debugLogA("dccmainthread(): end. DCC Server Thread Ending");
}
예제 #3
0
BOOL CJabberProto::OnIqRequestOOB(HXML, CJabberIqInfo *pInfo)
{
	if (!pInfo->GetFrom() || !pInfo->GetHContact())
		return TRUE;

	HXML n = XmlGetChild(pInfo->GetChildNode(), "url");
	if (!n || !XmlGetText(n))
		return TRUE;

	if (m_options.BsOnlyIBB) {
		// reject
		XmlNodeIq iq(_T("error"), pInfo);
		HXML e = XmlAddChild(iq, _T("error"), _T("File transfer refused")); XmlAddAttr(e, _T("code"), 406);
		m_ThreadInfo->send(iq);
		return TRUE;
	}

	filetransfer *ft = new filetransfer(this);
	ft->std.totalFiles = 1;
	ft->jid = mir_tstrdup(pInfo->GetFrom());
	ft->std.hContact = pInfo->GetHContact();
	ft->type = FT_OOB;
	ft->httpHostName = NULL;
	ft->httpPort = 80;
	ft->httpPath = NULL;

	// Parse the URL
	TCHAR *str = (TCHAR*)XmlGetText(n);	// URL of the file to get
	if (!_tcsnicmp(str, _T("http://"), 7)) {
		TCHAR *p = str + 7, *q;
		if ((q = _tcschr(p, '/')) != NULL) {
			TCHAR text[1024];
			if (q - p < _countof(text)) {
				_tcsncpy_s(text, p, q - p);
				text[q - p] = '\0';
				if ((p = _tcschr(text, ':')) != NULL) {
					ft->httpPort = (WORD)_ttoi(p + 1);
					*p = '\0';
				}
				ft->httpHostName = mir_t2a(text);
			}
		}
	}

	if (pInfo->GetIdStr())
		ft->szId = JabberId2string(pInfo->GetIqId());

	if (ft->httpHostName && ft->httpPath) {
		TCHAR *desc = NULL;

		debugLogA("Host=%s Port=%d Path=%s", ft->httpHostName, ft->httpPort, ft->httpPath);
		if ((n = XmlGetChild(pInfo->GetChildNode(), "desc")) != NULL)
			desc = (TCHAR*)XmlGetText(n);

		TCHAR *str2;
		debugLog(_T("description = %s"), desc);
		if ((str2 = _tcsrchr(ft->httpPath, '/')) != NULL)
			str2++;
		else
			str2 = ft->httpPath;
		str2 = mir_tstrdup(str2);
		JabberHttpUrlDecode(str2);

		PROTORECVFILET pre;
		pre.dwFlags = PRFF_TCHAR;
		pre.timestamp = time(NULL);
		pre.descr.t = desc;
		pre.files.t = &str2;
		pre.fileCount = 1;
		pre.lParam = (LPARAM)ft;
		ProtoChainRecvFile(ft->std.hContact, &pre);
		mir_free(str2);
	}
	else {
		// reject
		XmlNodeIq iq(_T("error"), pInfo);
		HXML e = XmlAddChild(iq, _T("error"), _T("File transfer refused")); XmlAddAttr(e, _T("code"), 406);
		m_ThreadInfo->send(iq);
		delete ft;
	}
	return TRUE;
}
예제 #4
0
// pszDescription points to a string with the reason
// buf points to the first data after the string
void CIcqProto::handleFileRequest(PBYTE buf, WORD wLen, DWORD dwUin, DWORD dwCookie, DWORD dwID1, DWORD dwID2, char* pszDescription, int nVersion, BOOL bDC)
{
	BOOL bEmptyDesc = FALSE;
	if (strlennull(pszDescription) == 0) {
		pszDescription = Translate("No description given");
		bEmptyDesc = TRUE;
	}

	// Empty port+pad
	buf += 4;
	wLen -= 4;

	// Filename
	WORD wFilenameLength;
	unpackLEWord(&buf, &wFilenameLength);
	if (!wFilenameLength) {
		NetLog_Direct("Ignoring malformed file send request");
		return;
	}
	
	char *pszFileName = (char*)_alloca(wFilenameLength + 1);
	unpackString(&buf, pszFileName, wFilenameLength);
	pszFileName[wFilenameLength] = '\0';

	wLen = wLen - 2 - wFilenameLength;

	// Total filesize
	DWORD dwFileSize;
	unpackLEDWord(&buf, &dwFileSize);
	wLen -= 4;

	int bAdded;
	HANDLE hContact = HContactFromUIN(dwUin, &bAdded);

	// Initialize a filetransfer struct
	filetransfer *ft = CreateFileTransfer(hContact, dwUin, nVersion);
	ft->dwCookie = dwCookie;
	ft->szFilename = mir_strdup(pszFileName);
	ft->szDescription = 0;
	ft->fileId = -1;
	ft->dwTotalSize = dwFileSize;
	ft->pMessage.dwMsgID1 = dwID1;
	ft->pMessage.dwMsgID2 = dwID2;
	ft->bDC = bDC;
	ft->bEmptyDesc = bEmptyDesc;

	// Send chain event
	TCHAR* ptszFileName = mir_utf8decodeT(pszFileName);

	PROTORECVFILET pre = {0};
	pre.flags = PREF_TCHAR;
	pre.fileCount = 1;
	pre.timestamp = time(NULL);
	pre.tszDescription = mir_utf8decodeT(pszDescription);
	pre.ptszFiles = &ptszFileName;
	pre.lParam = (LPARAM)ft;
	ProtoChainRecvFile(hContact, &pre);

	mir_free(pre.tszDescription);
	mir_free(ptszFileName);
}
예제 #5
0
// incoming transfer flow
void CToxProto::OnFriendFile(Tox*, uint32_t friendNumber, uint32_t fileNumber, uint32_t kind, uint64_t fileSize, const uint8_t *fileName, size_t filenameLength, void *arg)
{
	CToxProto *proto = (CToxProto*)arg;

	MCONTACT hContact = proto->GetContact(friendNumber);
	if (hContact)
	{
		switch (kind)
		{
		case TOX_FILE_KIND_AVATAR:
			{
				proto->logger->Log(__FUNCTION__": incoming avatar (%d) from (%d)", fileNumber, friendNumber);

				ptrT address(proto->getTStringA(hContact, TOX_SETTINGS_ID));
				TCHAR avatarName[MAX_PATH];
				mir_sntprintf(avatarName, MAX_PATH, _T("%s.png"), address);

				AvatarTransferParam *transfer = new AvatarTransferParam(friendNumber, fileNumber, avatarName, fileSize);
				transfer->pfts.flags |= PFTS_RECEIVING;
				transfer->pfts.hContact = hContact;
				proto->transfers.Add(transfer);

				TOX_ERR_FILE_GET error;
				tox_file_get_file_id(proto->toxThread->tox, friendNumber, fileNumber, transfer->hash, &error);
				if (error != TOX_ERR_FILE_GET_OK)
				{
					proto->logger->Log(__FUNCTION__": unable to get avatar hash (%d) from (%d) cause (%d)", fileNumber, friendNumber, error);
					memset(transfer->hash, 0, TOX_HASH_LENGTH);
				}
				proto->OnGotFriendAvatarInfo(transfer);
			}
			break;

		case TOX_FILE_KIND_DATA:
			{
				proto->logger->Log(__FUNCTION__": incoming file (%d) from (%d)", fileNumber, friendNumber);

				ptrA rawName((char*)mir_alloc(filenameLength + 1));
				memcpy(rawName, fileName, filenameLength);
				rawName[filenameLength] = 0;
				TCHAR *name = mir_utf8decodeT(rawName);

				FileTransferParam *transfer = new FileTransferParam(friendNumber, fileNumber, name, fileSize);
				transfer->pfts.flags |= PFTS_RECEIVING;
				transfer->pfts.hContact = hContact;
				proto->transfers.Add(transfer);

				PROTORECVFILET pre = { 0 };
				pre.dwFlags = PRFF_TCHAR;
				pre.fileCount = 1;
				pre.timestamp = time(NULL);
				pre.descr.t = _T("");
				pre.files.t = &name;
				pre.lParam = (LPARAM)transfer;
				ProtoChainRecvFile(hContact, &pre);
			}
			break;

		default:
			proto->logger->Log(__FUNCTION__": unsupported transfer (%d) from (%d) with type (%d)", fileNumber, friendNumber, kind);
			return;
		}
	}
}
예제 #6
0
void __cdecl TlenProcessP2P(XmlNode *node, ThreadData *info) {
	XmlNode *queryNode;
	TLEN_LIST_ITEM *item;
	char *from;

	if (info == NULL) return;

	queryNode = TlenXmlGetChild(node, "query");
	if ((from=TlenXmlGetAttrValue(node, "from")) != NULL) {
		XmlNode *fs , *vs, *dcng, *dc;
		/* file send */
		fs = TlenXmlGetChild(queryNode, "fs");
		/* voice send */
		vs  = TlenXmlGetChild(queryNode, "vs");
		dcng  = TlenXmlGetChild(queryNode, "dcng");
		dc  = TlenXmlGetChild(queryNode, "dc");
		if (fs  != NULL) {
			char *e, *id;
			/* e - step in the process (starting with 1)*/
			/* i - id of the file */
			/* s - size of the file */
			/* c - number of files */
			/* v - ??? */
			e = TlenXmlGetAttrValue(fs, "e");
			id = TlenXmlGetAttrValue(fs, "i");
			if (e != NULL) {
				if (!strcmp(e, "1")) {
					char *c, *s;
					TLEN_FILE_TRANSFER * ft = (TLEN_FILE_TRANSFER *) mir_alloc(sizeof(TLEN_FILE_TRANSFER));
					memset(ft, 0, sizeof(TLEN_FILE_TRANSFER));
					c = TlenXmlGetAttrValue(fs, "c");
					s = TlenXmlGetAttrValue(fs, "s");
					ft->jid = mir_strdup(from);
					ft->proto = info->proto;
					ft->hContact = TlenHContactFromJID(info->proto, from);
					ft->iqId = mir_strdup(id);
					ft->fileTotalSize = atoi(s);
					ft->newP2P = TRUE;
					if ((item=TlenListAdd(ft->proto, LIST_FILE, ft->iqId)) != NULL) {
						char fileInfo[128];
						item->ft = ft;
						mir_snprintf(fileInfo, SIZEOF(fileInfo), "%s file(s), %s bytes", c, s);
						TCHAR* filenameT = mir_utf8decodeT((char*)fileInfo);
						PROTORECVFILET pre = {0};
						pre.flags = PREF_TCHAR;
						pre.fileCount = 1;
						pre.timestamp = time(NULL);
						pre.tszDescription = filenameT;
						pre.ptszFiles = &filenameT;
						pre.lParam = (LPARAM)ft;
						ft->proto->debugLogA("sending chainrecv");
						ProtoChainRecvFile(ft->hContact, &pre);
						mir_free(filenameT);
					}
				} else if (!strcmp(e, "3")) {
					/* transfer error */
				} else if (!strcmp(e, "4")) {
					/* transfer denied */
				} else if (!strcmp(e, "5")) {
					/* transfer accepted */
					if ((item=TlenListGetItemPtr(info->proto, LIST_FILE, id)) != NULL) {
						item->id2 = mir_strdup("84273372");
						item->ft->id2 = mir_strdup("84273372");
						TlenSend(info->proto, "<iq to='%s'><query xmlns='p2p'><dcng n='file_send' k='5' v='2' s='1' i='%s' ck='o7a32V9n2UZYCWpBUhSbFw==' ks='16' iv='MhjWEj9WTsovrQc=o7a32V9n2UZYCWpBUhSbFw==' mi='%s'/></query></iq>", from, item->id2, id);
					}
				}
			}
		} else if (vs != NULL) {

		} else if (dcng != NULL) {
			char *s, *id, *id2;
			info->proto->debugLogA("DCNG");
			s = TlenXmlGetAttrValue(dcng, "s");
			id2 = TlenXmlGetAttrValue(dcng, "i");
			id = TlenXmlGetAttrValue(dcng, "mi");
			if (!strcmp(s, "1")) {
				/* Keys */
				/* n - name (file_send) */
				/* k - ??? */
				/* v - ??? */
				/* s - step */
				/* i - id of the file */
				/* ck - aes key */
				/* ks - key size (in bytes) */
				/* iv - aes initial vector */
				/* mi - p2p connection id */
				char *n, *k, *v, *ck, *iv;
				n = TlenXmlGetAttrValue(dcng, "n");
				k = TlenXmlGetAttrValue(dcng, "k");
				v = TlenXmlGetAttrValue(dcng, "v");
				ck = TlenXmlGetAttrValue(dcng, "ck");
				iv = TlenXmlGetAttrValue(dcng, "iv");
				if (!strcmp(n, "file_send")) {
					if ((item=TlenListGetItemPtr(info->proto, LIST_FILE, id)) != NULL) {
						item->id2 = mir_strdup(id2);
						item->ft->id2 = mir_strdup(id2);
						TlenBindUDPSocket(item->ft);
						TlenSend(info->proto, "<iq to='%s'><query xmlns='p2p'><dcng  la='%s' lp='%d' pa='%s' pp='%d' i='%s' v='2' k='5' s='2'/></query></iq>",
							item->ft->jid, item->ft->localName, item->ft->wLocalPort, item->ft->localName, item->ft->wLocalPort, item->ft->id2);
					}
				}
			}  else if (!strcmp(s, "2")) {
				info->proto->debugLogA("step = 2");
				info->proto->debugLogA("%s",from);
				info->proto->debugLogA("%s",id2);
				/* IP and port */
				if ((item=TlenListFindItemPtrById2(info->proto, LIST_FILE, id2)) != NULL) {
					item->ft->hostName = mir_strdup(TlenXmlGetAttrValue(dcng, "pa"));
					item->ft->wPort = atoi(TlenXmlGetAttrValue(dcng, "pp"));
					TlenBindUDPSocket(item->ft);
					TlenSend(info->proto, "<iq to='%s'><query xmlns='p2p'><dcng  la='%s' lp='%d' pa='%s' pp='%d' i='%s' k='5' s='4'/></query></iq>",
						item->ft->jid, item->ft->localName, item->ft->wLocalPort, item->ft->localName, item->ft->wLocalPort, item->ft->id2);
					forkthread((void (__cdecl *)(void*))TlenNewFileReceiveThread, 0, item->ft);
					forkthread((void (__cdecl *)(void*))TlenNewFileSendThread, 0, item->ft);
				}
			} else if (!strcmp(s, "4")) {
				/* IP and port */
				if ((item=TlenListFindItemPtrById2(info->proto, LIST_FILE, id2)) != NULL) {
					info->proto->debugLogA("step = 4");
					item->ft->hostName = mir_strdup(TlenXmlGetAttrValue(dcng, "pa"));
					item->ft->wPort = atoi(TlenXmlGetAttrValue(dcng, "pp"));
					forkthread((void (__cdecl *)(void*))TlenNewFileReceiveThread, 0, item->ft);
				}
			}

		} else if (dc != NULL) {

		}
	}
}