summaryrefslogtreecommitdiff
path: root/protocols/Gadu-Gadu/filetransfer.c
diff options
context:
space:
mode:
authorGeorge Hazan <george.hazan@gmail.com>2012-07-15 16:44:52 +0000
committerGeorge Hazan <george.hazan@gmail.com>2012-07-15 16:44:52 +0000
commit4649bcfc2b1cbbe2f004d7bec963a7528866c072 (patch)
treec6619f8f08266c740dc4e9783396f4f614319e1f /protocols/Gadu-Gadu/filetransfer.c
parent43691e8134fab2a55243607b2047c2fb3f3ee04b (diff)
z całym szacunkiem dla naszych polskich użytkowników
git-svn-id: http://svn.miranda-ng.org/main/trunk@977 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'protocols/Gadu-Gadu/filetransfer.c')
-rw-r--r--protocols/Gadu-Gadu/filetransfer.c982
1 files changed, 0 insertions, 982 deletions
diff --git a/protocols/Gadu-Gadu/filetransfer.c b/protocols/Gadu-Gadu/filetransfer.c
deleted file mode 100644
index cc55b993b8..0000000000
--- a/protocols/Gadu-Gadu/filetransfer.c
+++ /dev/null
@@ -1,982 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-// Gadu-Gadu Plugin for Miranda IM
-//
-// Copyright (c) 2003-2006 Adam Strzelecki <ono+miranda@java.pl>
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-////////////////////////////////////////////////////////////////////////////////
-
-#include "gg.h"
-#include <errno.h>
-#include <io.h>
-#include <fcntl.h>
-
-void __cdecl gg_dccmainthread(GGPROTO *gg, void *empty);
-
-void gg_dccstart(GGPROTO *gg)
-{
- DWORD exitCode = 0;
-
- if(gg->dcc) return;
-
- // Startup dcc thread
- GetExitCodeThread(gg->pth_dcc.hThread, &exitCode);
- // Check if dcc thread isn't running already
- if(exitCode == STILL_ACTIVE)
- {
-#ifdef DEBUGMODE
- gg_netlog(gg, "gg_dccstart(): DCC thread still active. Exiting...");
-#endif
- // Signalize mainthread it's started
- if(gg->event) SetEvent(gg->event);
- return;
- }
-
- // Check if we wan't direct connections
- if (!DBGetContactSettingByte(NULL, GG_PROTO, GG_KEY_DIRECTCONNS, GG_KEYDEF_DIRECTCONNS))
- {
- gg_netlog(gg, "gg_dccstart(): No direct connections setup.");
- if(gg->event) SetEvent(gg->event);
- return;
- }
-
- // Start thread
- gg->pth_dcc.hThread = gg_forkthreadex(gg, gg_dccmainthread, NULL, &gg->pth_dcc.dwThreadId);
-}
-
-void gg_dccconnect(GGPROTO *gg, uin_t uin)
-{
- struct gg_dcc *dcc;
- HANDLE hContact = gg_getcontact(gg, uin, 0, 0, NULL);
- DWORD ip, myuin; WORD port;
-
- gg_netlog(gg, "gg_dccconnect(): Connecting to uin %d.", uin);
-
- // If unknown user or not on list ignore
- if (!hContact) return;
-
- // Read user IP and port
- ip = swap32(DBGetContactSettingDword(hContact, GG_PROTO, GG_KEY_CLIENTIP, 0));
- port = DBGetContactSettingWord(hContact, GG_PROTO, GG_KEY_CLIENTPORT, 0);
- myuin = DBGetContactSettingDword(NULL, GG_PROTO, GG_KEY_UIN, 0);
-
- // If not port nor ip nor my uin (?) specified
- if (!ip || !port || !uin) return;
-
- if (!(dcc = gg_dcc_get_file(ip, port, myuin, uin)))
- return;
-
- // Add client dcc to watches
- EnterCriticalSection(&gg->ft_mutex);
- list_add(&gg->watches, dcc, 0);
- LeaveCriticalSection(&gg->ft_mutex);
-}
-
-//////////////////////////////////////////////////////////
-// THREAD: File transfer fail
-struct ftfaildata
-{
- HANDLE hContact;
- HANDLE hProcess;
-};
-void __cdecl gg_ftfailthread(GGPROTO *gg, void *param)
-{
- struct ftfaildata *ft = (struct ftfaildata *)param;
- SleepEx(100, FALSE);
- gg_netlog(gg, "gg_ftfailthread(): Sending failed file transfer.");
- ProtoBroadcastAck(GG_PROTO, ft->hContact, ACKTYPE_FILE, ACKRESULT_FAILED, ft->hProcess, 0);
- free(ft);
-}
-HANDLE ftfail(GGPROTO *gg, HANDLE hContact)
-{
- struct ftfaildata *ft = malloc(sizeof(struct ftfaildata));
-#ifdef DEBUGMODE
- gg_netlog(gg, "gg_ftfail(): Failing file transfer...");
-#endif
- srand(time(NULL));
- ft->hProcess = (HANDLE)rand();
- ft->hContact = hContact;
- gg_forkthread(gg, gg_ftfailthread, ft);
- return ft->hProcess;
-}
-
-////////////////////////////////////////////////////////////
-// Main DCC connection session thread
-
-// Info refresh min time (msec) / half-sec
-#define GGSTATREFRESHEVERY 500
-
-void __cdecl gg_dccmainthread(GGPROTO *gg, void *empty)
-{
- uin_t uin;
- struct gg_event *e;
- struct timeval tv;
- fd_set rd, wd;
- int ret;
- SOCKET maxfd;
- DWORD tick;
- list_t l;
- char filename[MAX_PATH];
-
- // Zero up lists
- gg->watches = gg->transfers = gg->requests = l = NULL;
-
- gg_netlog(gg, "gg_dccmainthread(): DCC Server Thread Starting");
-
- // Readup number
- if (!(uin = DBGetContactSettingDword(NULL, GG_PROTO, GG_KEY_UIN, 0)))
- {
- gg_netlog(gg, "gg_dccmainthread(): No Gadu-Gadu number specified. Exiting.");
- if(gg->event) SetEvent(gg->event);
- return;
- }
-
- // Create listen socket on config direct port
- if (!(gg->dcc = gg_dcc_socket_create(uin, (uint16_t)DBGetContactSettingWord(NULL, GG_PROTO, GG_KEY_DIRECTPORT, GG_KEYDEF_DIRECTPORT))))
- {
- gg_netlog(gg, "gg_dccmainthread(): Cannot create DCC listen socket. Exiting.");
- // Signalize mainthread we haven't start
- if(gg->event) SetEvent(gg->event);
- return;
- }
-
- gg_dcc_port = gg->dcc->port;
- gg_dcc_ip = inet_addr("255.255.255.255");
- gg_netlog(gg, "gg_dccmainthread(): Listening on port %d.", gg_dcc_port);
-
- // Signalize mainthread we started
- if(gg->event) SetEvent(gg->event);
-
- // Add main dcc handler to watches
- list_add(&gg->watches, gg->dcc, 0);
-
- // Do while we are in the main server thread
- while(gg->pth_dcc.dwThreadId && gg->dcc)
- {
- // Timeouts
- tv.tv_sec = 1;
- tv.tv_usec = 0;
-
- // Prepare descriptiors for select
- FD_ZERO(&rd);
- FD_ZERO(&wd);
-
- for (maxfd = 0, l = gg->watches; l; l = l->next)
- {
- struct gg_common *w = 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)
- gg_netlog(gg, "gg_dccmainthread(): Bad descriptor on select().");
- else if (errno != EINTR)
- gg_netlog(gg, "gg_dccmainthread(): Unknown error on select().");
- continue;
- }
-
- // Process watches (carefull with l)
- l = gg->watches;
- EnterCriticalSection(&gg->ft_mutex);
- while (l)
- {
- struct gg_common *c = l->data;
- struct gg_dcc *dcc = l->data;
- struct gg_dcc7 *dcc7 = l->data;
- l = l->next;
-
- switch (c->type)
- {
- default:
- if (!dcc || (!FD_ISSET(dcc->fd, &rd) && !FD_ISSET(dcc->fd, &wd)))
- continue;
-
- /////////////////////////////////////////////////////////////////
- // Process DCC events
-
- // Connection broken/closed
- if (!(e = gg_dcc_socket_watch_fd(dcc)))
- {
- gg_netlog(gg, "gg_dccmainthread(): Socket closed.");
- // Remove socket and _close
- list_remove(&gg->watches, dcc, 0);
- gg_dcc_socket_free(dcc);
-
- // Check if it's main socket
- if(dcc == gg->dcc) gg->dcc = NULL;
- continue;
- }
- else gg_netlog(gg, "gg_dccmainthread(): Event: %s", ggdebug_eventtype(e));
-
- switch(e->type)
- {
- // Client connected
- case GG_EVENT_DCC_NEW:
- list_add(&gg->watches, e->event.dcc_new, 0);
- e->event.dcc_new = NULL;
- break;
-
- //
- case GG_EVENT_NONE:
- // If transfer in progress do status
- if(dcc->file_fd != -1 && dcc->offset > 0 && (((tick = GetTickCount()) - dcc->tick) > GGSTATREFRESHEVERY))
- {
- PROTOFILETRANSFERSTATUS pfts;
- dcc->tick = tick;
- strncpy(filename, dcc->folder, sizeof(filename));
- strncat(filename, dcc->file_info.filename, sizeof(filename) - strlen(filename));
- memset(&pfts, 0, sizeof(PROTOFILETRANSFERSTATUS));
- pfts.cbSize = sizeof(PROTOFILETRANSFERSTATUS);
- pfts.hContact = (HANDLE)dcc->contact;
- pfts.flags = (dcc->type == GG_SESSION_DCC_SEND);
- pfts.pszFiles = NULL;
- pfts.totalFiles = 1;
- pfts.currentFileNumber = 0;
- pfts.totalBytes = dcc->file_info.size;
- pfts.totalProgress = dcc->offset;
- pfts.szWorkingDir = dcc->folder;
- pfts.szCurrentFile = filename;
- pfts.currentFileSize = dcc->file_info.size;
- pfts.currentFileProgress = dcc->offset;
- pfts.currentFileTime = 0;
- ProtoBroadcastAck(GG_PROTO, dcc->contact, ACKTYPE_FILE, ACKRESULT_DATA, dcc, (LPARAM)&pfts);
- }
- break;
-
- // Connection was successfuly ended
- case GG_EVENT_DCC_DONE:
- gg_netlog(gg, "gg_dccmainthread(): Client: %d, Transfer done ! Closing connection.", dcc->peer_uin);
- // Remove from watches
- list_remove(&gg->watches, dcc, 0);
- // Close file & success
- if(dcc->file_fd != -1)
- {
- PROTOFILETRANSFERSTATUS pfts;
- strncpy(filename, dcc->folder, sizeof(filename));
- strncat(filename, dcc->file_info.filename, sizeof(filename) - strlen(filename));
- memset(&pfts, 0, sizeof(PROTOFILETRANSFERSTATUS));
- pfts.cbSize = sizeof(PROTOFILETRANSFERSTATUS);
- pfts.hContact = (HANDLE)dcc->contact;
- pfts.flags = (dcc->type == GG_SESSION_DCC_SEND);
- pfts.pszFiles = NULL;
- pfts.totalFiles = 1;
- pfts.currentFileNumber = 0;
- pfts.totalBytes = dcc->file_info.size;
- pfts.totalProgress = dcc->file_info.size;
- pfts.szWorkingDir = dcc->folder;
- pfts.szCurrentFile = filename;
- pfts.currentFileSize = dcc->file_info.size;
- pfts.currentFileProgress = dcc->file_info.size;
- pfts.currentFileTime = 0;
- ProtoBroadcastAck(GG_PROTO, dcc->contact, ACKTYPE_FILE, ACKRESULT_DATA, dcc, (LPARAM)&pfts);
- _close(dcc->file_fd); dcc->file_fd = -1;
- ProtoBroadcastAck(GG_PROTO, dcc->contact, ACKTYPE_FILE, ACKRESULT_SUCCESS, dcc, 0);
- }
- // Free dcc
- gg_free_dcc(dcc); if(dcc == gg->dcc) gg->dcc = NULL;
- break;
-
- // Client error
- case GG_EVENT_DCC_ERROR:
- switch (e->event.dcc_error)
- {
- case GG_ERROR_DCC_HANDSHAKE:
- gg_netlog(gg, "gg_dccmainthread(): Client: %d, Handshake error.", dcc->peer_uin);
- break;
- case GG_ERROR_DCC_NET:
- gg_netlog(gg, "gg_dccmainthread(): Client: %d, Network error.", dcc->peer_uin);
- break;
- case GG_ERROR_DCC_FILE:
- gg_netlog(gg, "gg_dccmainthread(): Client: %d, File read/write error.", dcc->peer_uin);
- break;
- case GG_ERROR_DCC_EOF:
- gg_netlog(gg, "gg_dccmainthread(): Client: %d, End of file/connection error.", dcc->peer_uin);
- break;
- case GG_ERROR_DCC_REFUSED:
- gg_netlog(gg, "gg_dccmainthread(): Client: %d, Connection refused error.", dcc->peer_uin);
- break;
- default:
- gg_netlog(gg, "gg_dccmainthread(): Client: %d, Unknown error.", dcc->peer_uin);
- }
- // Don't do anything if it's main socket
- if(dcc == gg->dcc) break;
-
- // Remove from watches
- list_remove(&gg->watches, dcc, 0);
-
- // Close file & fail
- if(dcc->contact)
- {
- _close(dcc->file_fd); dcc->file_fd = -1;
- ProtoBroadcastAck(GG_PROTO, dcc->contact, ACKTYPE_FILE, ACKRESULT_FAILED, dcc, 0);
- }
- // Free dcc
- gg_free_dcc(dcc); if(dcc == gg->dcc) gg->dcc = NULL;
- break;
-
- // Need file acknowledgement
- case GG_EVENT_DCC_NEED_FILE_ACK:
- gg_netlog(gg, "gg_dccmainthread(): Client: %d, File ack filename \"%s\" size %d.", dcc->peer_uin,
- dcc->file_info.filename, dcc->file_info.size);
- // Do not watch for transfer until user accept it
- list_remove(&gg->watches, dcc, 0);
- // Add to waiting transfers
- list_add(&gg->transfers, dcc, 0);
-
- //////////////////////////////////////////////////
- // Add file recv request
- {
- CCSDATA ccs;
- PROTORECVEVENT pre;
- char *szBlob;
- char *szFilename = dcc->file_info.filename;
- char *szMsg = dcc->file_info.filename;
-
- // Make new ggtransfer struct
- dcc->contact = gg_getcontact(gg, dcc->peer_uin, 0, 0, NULL);
- szBlob = (char *)malloc(sizeof(DWORD) + strlen(szFilename) + strlen(szMsg) + 2);
- // Store current dcc
- *(PDWORD)szBlob = (DWORD)dcc;
- // Store filename
- strcpy(szBlob + sizeof(DWORD), szFilename);
- // Store description
- strcpy(szBlob + sizeof(DWORD) + strlen(szFilename) + 1, szMsg);
- ccs.szProtoService = PSR_FILE;
- ccs.hContact = dcc->contact;
- ccs.wParam = 0;
- ccs.lParam = (LPARAM)&pre;
- pre.flags = 0;
- pre.timestamp = time(NULL);
- pre.szMessage = szBlob;
- pre.lParam = 0;
- CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);
- free(szBlob);
- }
- break;
-
- // Need client accept
- case GG_EVENT_DCC_CLIENT_ACCEPT:
- gg_netlog(gg, "gg_dccmainthread(): Client: %d, Client accept.", dcc->peer_uin);
- // Check if user is on the list and if it is my uin
- if(gg_getcontact(gg, dcc->peer_uin, 0, 0, NULL) &&
- DBGetContactSettingDword(NULL, GG_PROTO, GG_KEY_UIN, -1) == dcc->uin)
- break;
-
- // Kill unauthorized dcc
- list_remove(&gg->watches, dcc, 0);
- gg_free_dcc(dcc); if(dcc == gg->dcc) gg->dcc = NULL;
- break;
-
- // Client connected as we wished to (callback)
- case GG_EVENT_DCC_CALLBACK:
- {
- int found = 0;
- gg_netlog(gg, "gg_dccmainthread(): Callback from client %d.", dcc->peer_uin);
- // Seek for stored callback request
- for (l = gg->requests; l; l = l->next)
- {
- struct gg_dcc *req = l->data;
-
- if (req && req->peer_uin == dcc->peer_uin)
- {
- gg_dcc_set_type(dcc, GG_SESSION_DCC_SEND);
- found = 1;
-
- // Copy data req ===> dcc
- dcc->folder = req->folder;
- dcc->contact = req->contact;
- dcc->file_fd = req->file_fd;
- memcpy(&dcc->file_info, &req->file_info, sizeof(struct gg_file_info));
- // Copy data back to dcc ===> req
- memcpy(req, dcc, sizeof(struct gg_dcc));
-
- // Remove request
- list_remove(&gg->requests, req, 0);
- // Remove dcc from watches
- list_remove(&gg->watches, dcc, 0);
- // Add request to watches
- list_add(&gg->watches, req, 0);
- // Free old dat
- gg_free_dcc(dcc);
- gg_netlog(gg, "gg_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)
- {
- gg_netlog(gg, "gg_dccmainthread(): Unknown request to client %d.", dcc->peer_uin);
- // Kill unauthorized dcc
- list_remove(&gg->watches, dcc, 0);
- gg_free_dcc(dcc); if(dcc == gg->dcc) gg->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 (!dcc7 || (!FD_ISSET(dcc7->fd, &rd) && !FD_ISSET(dcc7->fd, &wd)))
- continue;
-
- /////////////////////////////////////////////////////////////////
- // Process DCC7 events
-
- // Connection broken/closed
- if (!(e = gg_dcc7_watch_fd(dcc7)))
- {
- gg_netlog(gg, "gg_dccmainthread(): Socket closed.");
- // Remove socket and _close
- list_remove(&gg->watches, dcc7, 0);
- gg_dcc7_free(dcc7);
- continue;
- }
- else gg_netlog(gg, "gg_dccmainthread(): Event: %s", ggdebug_eventtype(e));
-
- switch(e->type)
- {
- //
- case GG_EVENT_NONE:
- // If transfer in progress do status
- if(dcc7->file_fd != -1 && dcc7->offset > 0 && (((tick = GetTickCount()) - dcc7->tick) > GGSTATREFRESHEVERY))
- {
- PROTOFILETRANSFERSTATUS pfts;
- dcc7->tick = tick;
- strncpy(filename, dcc7->folder, sizeof(filename));
- strncat(filename, dcc7->filename, sizeof(filename) - strlen(filename));
- memset(&pfts, 0, sizeof(PROTOFILETRANSFERSTATUS));
- pfts.cbSize = sizeof(PROTOFILETRANSFERSTATUS);
- pfts.hContact = (HANDLE)dcc7->contact;
- pfts.flags = (dcc7->type == GG_SESSION_DCC7_SEND);
- pfts.pszFiles = NULL;
- pfts.totalFiles = 1;
- pfts.currentFileNumber = 0;
- pfts.totalBytes = dcc7->size;
- pfts.totalProgress = dcc7->offset;
- pfts.szWorkingDir = dcc7->folder;
- pfts.szCurrentFile = filename;
- pfts.currentFileSize = dcc7->size;
- pfts.currentFileProgress = dcc7->offset;
- pfts.currentFileTime = 0;
- ProtoBroadcastAck(GG_PROTO, dcc7->contact, ACKTYPE_FILE, ACKRESULT_DATA, dcc7, (LPARAM)&pfts);
- }
- break;
-
- // Connection was successfuly ended
- case GG_EVENT_DCC7_DONE:
- gg_netlog(gg, "gg_dccmainthread(): Client: %d, Transfer done ! Closing connection.", dcc->peer_uin);
- // Remove from watches
- list_remove(&gg->watches, dcc7, 0);
- // Close file & success
- if(dcc7->file_fd != -1)
- {
- PROTOFILETRANSFERSTATUS pfts;
- strncpy(filename, dcc7->folder, sizeof(filename));
- strncat(filename, dcc7->filename, sizeof(filename) - strlen(filename));
- memset(&pfts, 0, sizeof(PROTOFILETRANSFERSTATUS));
- pfts.cbSize = sizeof(PROTOFILETRANSFERSTATUS);
- pfts.hContact = (HANDLE)dcc7->contact;
- pfts.flags = (dcc7->type == GG_SESSION_DCC7_SEND);
- pfts.pszFiles = NULL;
- pfts.totalFiles = 1;
- pfts.currentFileNumber = 0;
- pfts.totalBytes = dcc7->size;
- pfts.totalProgress = dcc7->size;
- pfts.szWorkingDir = dcc7->folder;
- pfts.szCurrentFile = filename;
- pfts.currentFileSize = dcc7->size;
- pfts.currentFileProgress = dcc7->size;
- pfts.currentFileTime = 0;
- ProtoBroadcastAck(GG_PROTO, dcc7->contact, ACKTYPE_FILE, ACKRESULT_DATA, dcc7, (LPARAM)&pfts);
- _close(dcc7->file_fd); dcc7->file_fd = -1;
- ProtoBroadcastAck(GG_PROTO, dcc7->contact, ACKTYPE_FILE, ACKRESULT_SUCCESS, dcc7, 0);
- }
- // Free dcc
- gg_dcc7_free(dcc7);
- break;
-
- // Client error
- case GG_EVENT_DCC7_ERROR:
- switch (e->event.dcc7_error)
- {
- case GG_ERROR_DCC7_HANDSHAKE:
- gg_netlog(gg, "gg_dccmainthread(): Client: %d, Handshake error.", dcc7->peer_uin);
- break;
- case GG_ERROR_DCC7_NET:
- gg_netlog(gg, "gg_dccmainthread(): Client: %d, Network error.", dcc7->peer_uin);
- break;
- case GG_ERROR_DCC7_FILE:
- gg_netlog(gg, "gg_dccmainthread(): Client: %d, File read/write error.", dcc7->peer_uin);
- break;
- case GG_ERROR_DCC7_EOF:
- gg_netlog(gg, "gg_dccmainthread(): Client: %d, End of file/connection error.", dcc7->peer_uin);
- break;
- case GG_ERROR_DCC7_REFUSED:
- gg_netlog(gg, "gg_dccmainthread(): Client: %d, Connection refused error.", dcc7->peer_uin);
- break;
- case GG_ERROR_DCC7_RELAY:
- gg_netlog(gg, "gg_dccmainthread(): Client: %d, Relay connection error.", dcc7->peer_uin);
- break;
- default:
- gg_netlog(gg, "gg_dccmainthread(): Client: %d, Unknown error.", dcc7->peer_uin);
- }
- // Remove from watches
- list_remove(&gg->watches, dcc7, 0);
-
- // Close file & fail
- if (dcc7->file_fd != -1)
- {
- _close(dcc7->file_fd);
- dcc7->file_fd = -1;
- }
-
- if (dcc7->contact)
- ProtoBroadcastAck(GG_PROTO, dcc7->contact, ACKTYPE_FILE, ACKRESULT_FAILED, dcc7, 0);
-
- // Free dcc
- gg_dcc7_free(dcc7);
- break;
- }
-
- // Free event
- gg_free_event(e);
- break;
- }
- }
- LeaveCriticalSection(&gg->ft_mutex);
- }
-
- // Close all dcc client sockets
- for (l = gg->watches; l; l = l->next)
- {
- struct gg_common *c = 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 *dcc7 = l->data;
- gg_dcc7_free(dcc7);
- }
- else
- {
- struct gg_dcc *dcc = l->data;
- gg_dcc_socket_free(dcc);
-
- // Check if it's main socket
- if(dcc == gg->dcc) gg->dcc = NULL;
- }
- }
- // Close all waiting for aknowledgle transfers
- for (l = gg->transfers; l; l = l->next)
- {
- struct gg_common *c = 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 *dcc7 = l->data;
- gg_dcc7_free(dcc7);
- }
- else
- {
- struct gg_dcc *dcc = l->data;
- gg_dcc_socket_free(dcc);
- }
- }
- // Close all waiting dcc requests
- for (l = gg->requests; l; l = l->next)
- {
- struct gg_dcc *dcc = l->data;
- if(dcc) gg_free_dcc(dcc);
- }
- list_destroy(gg->watches, 0);
- list_destroy(gg->transfers, 0);
- list_destroy(gg->requests, 0);
-
- gg_dcc_port = 0;
- gg_dcc_ip = 0;
- gg_netlog(gg, "gg_dccmainthread(): DCC Server Thread Ending");
-}
-
-////////////////////////////////////////////////////////////
-// Called when received an file
-int gg_recvfile(PROTO_INTERFACE *proto, HANDLE hContact, PROTOFILEEVENT* pre)
-{
- CCSDATA ccs = { hContact, PSR_FILE, 0, ( LPARAM )pre };
- return CallService( MS_PROTO_RECVFILE, 0, ( LPARAM )&ccs );
-}
-
-////////////////////////////////////////////////////////////
-// Called when user sends a file
-HANDLE gg_sendfile(PROTO_INTERFACE *proto, HANDLE hContact, const PROTOCHAR* szDescription, PROTOCHAR** ppszFiles)
-{
- GGPROTO *gg = (GGPROTO *) proto;
- char *bslash, *filename;
- struct gg_dcc *dcc;
- DWORD ip, ver;
- WORD port;
- uin_t myuin, uin;
-
- // Check if main dcc thread is on
- if (!gg_isonline(gg)) return ftfail(gg, hContact);
-
- filename = gg_t2a(ppszFiles[0]);
-
- // Read user IP and port
- ip = swap32(DBGetContactSettingDword(hContact, GG_PROTO, GG_KEY_CLIENTIP, 0));
- port = DBGetContactSettingWord(hContact, GG_PROTO, GG_KEY_CLIENTPORT, 0);
- myuin = DBGetContactSettingDword(NULL, GG_PROTO, GG_KEY_UIN, 0);
- uin = DBGetContactSettingDword(hContact, GG_PROTO, GG_KEY_UIN, 0);
- ver = DBGetContactSettingDword(hContact, GG_PROTO, GG_KEY_CLIENTVERSION, 0);
-
- // Use DCC7 if a contact is using at least version 7.6 or unknown version
- if ((ver & 0x00ffffff) >= 0x29 || !ver) {
- struct gg_dcc7 *dcc7;
-
- EnterCriticalSection(&gg->sess_mutex);
- if (!(dcc7 = gg_dcc7_send_file(gg->sess, uin, filename, NULL, NULL))) {
- LeaveCriticalSection(&gg->sess_mutex);
- gg_netlog(gg, "gg_sendfile(): Failed to send file \"%s\".", filename);
- mir_free(filename);
- return ftfail(gg, hContact);
- }
- LeaveCriticalSection(&gg->sess_mutex);
-
- gg_netlog(gg, "gg_sendfile(): Sending file \"%s\" to %d.", filename, uin);
-
- // Add dcc to watches
- list_add(&gg->watches, dcc7, 0);
-
- // Store handle
- dcc7->contact = hContact;
- dcc7->folder = _strdup(filename);
- dcc7->tick = 0;
- // Make folder name
- bslash = strrchr(dcc7->folder, '\\');
- if(bslash)
- *(bslash + 1) = 0;
- else
- *(dcc7->folder) = 0;
- mir_free(filename);
- return dcc7;
- }
-
- // Return if bad connection info
- if (!port || !uin || !myuin)
- {
- gg_netlog(gg, "gg_sendfile(): Bad contact uin or my uin. Exit.");
- mir_free(filename);
- return ftfail(gg, hContact);
- }
-
- // Try to connect if not ask user to connect me
- if ((ip && port >= 10 && !(dcc = gg_dcc_send_file(ip, port, myuin, uin))) || (port < 10 && port > 0))
- {
- // Make fake dcc structure
- dcc = malloc(sizeof(struct gg_dcc));
- memset(dcc, 0, sizeof(struct gg_dcc));
- // Fill up structures
- dcc->uin = myuin;
- dcc->peer_uin = uin;
- dcc->fd = -1;
- dcc->type = GG_SESSION_DCC_SEND;
- gg_netlog(gg, "gg_sendfile(): Requesting user to connect us and scheduling gg_dcc struct for a later use.");
- EnterCriticalSection(&gg->sess_mutex);
- gg_dcc_request(gg->sess, uin);
- LeaveCriticalSection(&gg->sess_mutex);
- list_add(&gg->requests, dcc, 0);
- }
-
- // Write filename
- if(gg_dcc_fill_file_info(dcc, filename) == -1)
- {
- gg_netlog(gg, "gg_sendfile(): Cannot open and file fileinfo \"%s\".", filename);
- gg_free_dcc(dcc);
- mir_free(filename);
- return ftfail(gg, hContact);
- }
-
- gg_netlog(gg, "gg_sendfile(): Sending file \"%s\" to %d in %s mode.", filename, uin, (dcc->fd != -1) ? "active" : "passive");
-
- // Add dcc to watches if not passive
- if(dcc->fd != -1) list_add(&gg->watches, dcc, 0);
-
- // Store handle
- dcc->contact = hContact;
- dcc->folder = _strdup(filename);
- dcc->tick = 0;
- // Make folder name
- bslash = strrchr(dcc->folder, '\\');
- if(bslash)
- *(bslash + 1) = 0;
- else
- *(dcc->folder) = 0;
-
- mir_free(filename);
- return dcc;
-}
-
-HANDLE gg_dccfileallow(GGPROTO *gg, HANDLE hTransfer, const PROTOCHAR* szPath)
-{
- struct gg_dcc *dcc = (struct gg_dcc *) hTransfer;
- char fileName[MAX_PATH], *path = gg_t2a(szPath);
- strncpy(fileName, path, sizeof(fileName));
- strncat(fileName, dcc->file_info.filename, sizeof(fileName) - strlen(fileName));
- dcc->folder = _strdup((char *) path);
- dcc->tick = 0;
- mir_free(path);
-
- // Remove transfer from waiting list
- EnterCriticalSection(&gg->ft_mutex);
- list_remove(&gg->transfers, dcc, 0);
- LeaveCriticalSection(&gg->ft_mutex);
-
- // Open file for appending and check if ok
- if ((dcc->file_fd = _open(fileName, _O_WRONLY | _O_APPEND | _O_BINARY | _O_CREAT, _S_IREAD | _S_IWRITE)) == -1)
- {
- gg_netlog(gg, "gg_dccfileallow(): Failed to create file \"%s\".", fileName);
- ProtoBroadcastAck(GG_PROTO, dcc->contact, ACKTYPE_FILE, ACKRESULT_FAILED, dcc, 0);
- // Free transfer
- gg_free_dcc(dcc);
- return 0;
- }
-
- // Put an offset to the file
- dcc->offset = _lseek(dcc->file_fd, 0, SEEK_END);
-
- // Add to watches and start transfer
- EnterCriticalSection(&gg->ft_mutex);
- list_add(&gg->watches, dcc, 0);
- LeaveCriticalSection(&gg->ft_mutex);
-
- gg_netlog(gg, "gg_dccfileallow(): Receiving file \"%s\" from %d.", dcc->file_info.filename, dcc->peer_uin);
-
- return hTransfer;
-}
-
-HANDLE gg_dcc7fileallow(GGPROTO *gg, HANDLE hTransfer, const PROTOCHAR* szPath)
-{
- struct gg_dcc7 *dcc7 = (struct gg_dcc7 *) hTransfer;
- char fileName[MAX_PATH], *path = gg_t2a(szPath);
- int iFtRemoveRes;
- strncpy(fileName, path, sizeof(fileName));
- strncat(fileName, dcc7->filename, sizeof(fileName) - strlen(fileName));
- dcc7->folder = _strdup((char *) path);
- dcc7->tick = 0;
- mir_free(path);
-
- // Remove transfer from waiting list
- EnterCriticalSection(&gg->ft_mutex);
- iFtRemoveRes = list_remove(&gg->transfers, dcc7, 0);
- LeaveCriticalSection(&gg->ft_mutex);
-
- if (iFtRemoveRes == -1)
- {
- gg_netlog(gg, "gg_dcc7fileallow(): File transfer denied.");
- ProtoBroadcastAck(GG_PROTO, dcc7->contact, ACKTYPE_FILE, ACKRESULT_DENIED, dcc7, 0);
- // Free transfer
- gg_dcc7_free(dcc7);
- return 0;
- }
-
- // Open file for appending and check if ok
- if ((dcc7->file_fd = _open(fileName, _O_WRONLY | _O_APPEND | _O_BINARY | _O_CREAT, _S_IREAD | _S_IWRITE)) == -1)
- {
- gg_netlog(gg, "gg_dcc7fileallow(): Failed to create file \"%s\".", fileName);
- gg_dcc7_reject(dcc7, GG_DCC7_REJECT_USER);
- ProtoBroadcastAck(GG_PROTO, dcc7->contact, ACKTYPE_FILE, ACKRESULT_FAILED, dcc7, 0);
- // Free transfer
- gg_dcc7_free(dcc7);
- return 0;
- }
-
- // Put an offset to the file
- dcc7->offset = _lseek(dcc7->file_fd, 0, SEEK_END);
- gg_dcc7_accept(dcc7, dcc7->offset);
-
- // Add to watches and start transfer
- EnterCriticalSection(&gg->ft_mutex);
- list_add(&gg->watches, dcc7, 0);
- LeaveCriticalSection(&gg->ft_mutex);
-
- gg_netlog(gg, "gg_dcc7fileallow(): Receiving file \"%s\" from %d.", dcc7->filename, dcc7->peer_uin);
-
- return hTransfer;
-}
-
-////////////////////////////////////////////////////////////
-// File receiving allowed
-HANDLE gg_fileallow(PROTO_INTERFACE *proto, HANDLE hContact, HANDLE hTransfer, const PROTOCHAR* szPath)
-{
- struct gg_common *c = (struct gg_common *) hTransfer;
-
- // Check if its proper dcc
- if (!c) return NULL;
-
- if (c->type == GG_SESSION_DCC7_GET)
- return gg_dcc7fileallow((GGPROTO *)proto, hTransfer, szPath);
-
- return gg_dccfileallow((GGPROTO *)proto, hTransfer, szPath);
-}
-
-int gg_dccfiledeny(GGPROTO *gg, HANDLE hTransfer)
-{
- struct gg_dcc *dcc = (struct gg_dcc *) hTransfer;
-
- // Remove transfer from any list
- EnterCriticalSection(&gg->ft_mutex);
- if(gg->watches) list_remove(&gg->watches, dcc, 0);
- if(gg->requests) list_remove(&gg->requests, dcc, 0);
- if(gg->transfers) list_remove(&gg->transfers, dcc, 0);
- LeaveCriticalSection(&gg->ft_mutex);
-
- gg_netlog(gg, "gg_dccfiledeny(): Rejected file \"%s\" from/to %d.", dcc->file_info.filename, dcc->peer_uin);
-
- // Free transfer
- gg_free_dcc(dcc);
-
- return 0;
-}
-
-int gg_dcc7filedeny(GGPROTO *gg, HANDLE hTransfer)
-{
- struct gg_dcc7 *dcc7 = (struct gg_dcc7 *) hTransfer;
-
- gg_dcc7_reject(dcc7, GG_DCC7_REJECT_USER);
-
- // Remove transfer from any list
- EnterCriticalSection(&gg->ft_mutex);
- if(gg->watches) list_remove(&gg->watches, dcc7, 0);
- if(gg->transfers) list_remove(&gg->transfers, dcc7, 0);
- LeaveCriticalSection(&gg->ft_mutex);
-
- gg_netlog(gg, "gg_dcc7filedeny(): Rejected file \"%s\" from/to %d.", dcc7->filename, dcc7->peer_uin);
-
- // Free transfer
- gg_dcc7_free(dcc7);
-
- return 0;
-}
-
-////////////////////////////////////////////////////////////
-// File receiving denied
-int gg_filedeny(PROTO_INTERFACE *proto, HANDLE hContact, HANDLE hTransfer, const PROTOCHAR* szReason)
-{
- struct gg_common *c = (struct gg_common *) hTransfer;
-
- // Check if its proper dcc
- if (!c) return 0;
-
- if (c->type == GG_SESSION_DCC7_GET)
- return gg_dcc7filedeny((GGPROTO *)proto, hTransfer);
-
- return gg_dccfiledeny((GGPROTO *)proto, hTransfer);
-}
-
-int gg_dccfilecancel(GGPROTO *gg, HANDLE hTransfer)
-{
- struct gg_dcc *dcc = (struct gg_dcc *) hTransfer;
-
- // Remove transfer from any list
- EnterCriticalSection(&gg->ft_mutex);
- if(gg->watches) list_remove(&gg->watches, dcc, 0);
- if(gg->requests) list_remove(&gg->requests, dcc, 0);
- if(gg->transfers) list_remove(&gg->transfers, dcc, 0);
- LeaveCriticalSection(&gg->ft_mutex);
-
- // Send failed info
- ProtoBroadcastAck(GG_PROTO, dcc->contact, ACKTYPE_FILE, ACKRESULT_FAILED, dcc, 0);
- // Close file
- if(dcc->file_fd != -1)
- {
- _close(dcc->file_fd);
- dcc->file_fd = -1;
- }
-
- gg_netlog(gg, "gg_dccfilecancel(): Canceled file \"%s\" from/to %d.", dcc->file_info.filename, dcc->peer_uin);
-
- // Free transfer
- gg_free_dcc(dcc);
-
- return 0;
-}
-
-int gg_dcc7filecancel(GGPROTO *gg, HANDLE hTransfer)
-{
- struct gg_dcc7 *dcc7 = (struct gg_dcc7 *) hTransfer;
-
- if (dcc7->type == GG_SESSION_DCC7_SEND && dcc7->state == GG_STATE_WAITING_FOR_ACCEPT)
- gg_dcc7_abort(dcc7);
-
- // Remove transfer from any list
- EnterCriticalSection(&gg->ft_mutex);
- if(gg->watches) list_remove(&gg->watches, dcc7, 0);
- if(gg->transfers) list_remove(&gg->transfers, dcc7, 0);
- LeaveCriticalSection(&gg->ft_mutex);
-
- // Send failed info
- ProtoBroadcastAck(GG_PROTO, dcc7->contact, ACKTYPE_FILE, ACKRESULT_FAILED, dcc7, 0);
- // Close file
- if(dcc7->file_fd != -1)
- {
- _close(dcc7->file_fd);
- dcc7->file_fd = -1;
- }
-
- gg_netlog(gg, "gg_dcc7filecancel(): Canceled file \"%s\" from/to %d.", dcc7->filename, dcc7->peer_uin);
-
- // Free transfer
- gg_dcc7_free(dcc7);
-
- return 0;
-}
-
-////////////////////////////////////////////////////////////
-// File transfer canceled
-int gg_filecancel(PROTO_INTERFACE *proto, HANDLE hContact, HANDLE hTransfer)
-{
- GGPROTO *gg = (GGPROTO *) proto;
- struct gg_common *c = (struct gg_common *) hTransfer;
-
- // Check if its proper dcc
- if (!c) return 0;
-
- if (c->type == GG_SESSION_DCC7_SEND || c->type == GG_SESSION_DCC7_GET)
- return gg_dcc7filecancel((GGPROTO *) proto, hTransfer);
-
- return gg_dccfilecancel((GGPROTO *) proto, hTransfer);
-}