1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
4 * $Id: filesession.c 2509 2001-10-13 00:06:18Z warmenhoven $
6 * Copyright (C) 1998-2001, Denis V. Dmitrienko <denis@null.net> and
7 * Bill Soudan <soudan@kde.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
38 #include "filesession.h"
39 #include "stdpackets.h"
40 #include "socketmanager.h"
42 icq_FileSession
*icq_FileSessionNew(icq_Link
*icqlink
)
44 icq_FileSession
*p
=(icq_FileSession
*)malloc(sizeof(icq_FileSession
));
53 p
->current_file_num
=0;
54 p
->current_file_progress
=0;
55 p
->current_file_size
=0;
60 p
->total_transferred_bytes
=0;
63 icq_ListInsert(icqlink
->d
->icq_FileSessions
, 0, p
);
69 void icq_FileSessionDelete(void *pv
)
71 icq_FileSession
*p
=(icq_FileSession
*)pv
;
73 invoke_callback(p
->icqlink
, icq_FileNotify
)(p
, FILE_NOTIFY_CLOSE
, 0,
84 if (p
->current_fd
> -1 ) {
92 int _icq_FindFileSession(void *p
, va_list data
)
94 icq_FileSession
*psession
=(icq_FileSession
*)p
;
95 DWORD uin
=va_arg(data
, DWORD
);
96 unsigned long id
=va_arg(data
, unsigned long);
98 return (psession
->remote_uin
== uin
) && ( id
? (psession
->id
== id
) : 1 );
102 icq_FileSession
*icq_FindFileSession(icq_Link
*icqlink
, DWORD uin
,
105 return icq_ListTraverse(icqlink
->d
->icq_FileSessions
, _icq_FindFileSession
,
109 void icq_FileSessionSetStatus(icq_FileSession
*p
, int status
)
111 if(status
!=p
->status
)
115 invoke_callback(p
->icqlink
, icq_FileNotify
)(p
, FILE_NOTIFY_STATUS
,
117 if (status
== FILE_STATUS_SENDING
)
118 icq_SocketSetHandler(p
->tcplink
->socket
, ICQ_SOCKET_WRITE
,
119 (icq_SocketHandler
)icq_FileSessionSendData
, p
);
121 icq_SocketSetHandler(p
->tcplink
->socket
, ICQ_SOCKET_WRITE
, NULL
, NULL
);
125 void icq_FileSessionSetHandle(icq_FileSession
*p
, const char *handle
)
127 strncpy(p
->remote_handle
, handle
, 64);
130 void icq_FileSessionSetCurrentFile(icq_FileSession
*p
, const char *filename
)
133 struct _stat file_status
;
135 struct stat file_status
;
139 strcpy(file
, p
->working_dir
);
140 strcat(file
, filename
);
142 if (p
->current_fd
>-1) {
143 close(p
->current_fd
);
147 strncpy(p
->current_file
, file
, 64);
148 p
->current_file_progress
=0;
150 /* does the file already exist? */
152 if (_stat(file
, &file_status
)==0) {
154 if (stat(file
, &file_status
)==0) {
156 p
->current_file_progress
=file_status
.st_size
;
157 p
->total_transferred_bytes
+=file_status
.st_size
;
159 p
->current_fd
=open(file
, _O_WRONLY
| _O_APPEND
| _O_BINARY
);
161 p
->current_fd
=open(file
, O_WRONLY
| O_APPEND
);
165 p
->current_fd
=open(file
, _O_WRONLY
| _O_CREAT
| _O_BINARY
,
168 p
->current_fd
=open(file
, O_WRONLY
| O_CREAT
, S_IRWXU
);
172 /* make sure we have a valid filehandle */
173 if (p
->current_fd
== -1)
174 perror("couldn't open file: ");
178 void icq_FileSessionPrepareNextFile(icq_FileSession
*p
)
181 char **files
=p
->files
;
183 p
->current_file_num
++;
187 if(i
==p
->current_file_num
)
195 struct _stat file_status
;
197 struct stat file_status
;
200 if (p
->current_fd
>-1) {
201 close(p
->current_fd
);
206 if (_stat(*files
, &file_status
)==0) {
207 char *basename
=*files
;
208 char *pos
=strrchr(basename
, '\\');
210 if (stat(*files
, &file_status
)==0) {
211 char *basename
=*files
;
212 char *pos
=strrchr(basename
, '/');
214 if(pos
) basename
=pos
+1;
215 strncpy(p
->current_file
, basename
, 64);
216 p
->current_file_progress
=0;
217 p
->current_file_size
=file_status
.st_size
;
219 p
->current_fd
=open(*files
, _O_RDONLY
| _O_BINARY
);
221 p
->current_fd
=open(*files
, O_RDONLY
);
225 /* make sure we have a valid filehandle */
226 if (p
->current_fd
== -1)
227 perror("couldn't open file: ");
231 void icq_FileSessionSendData(icq_FileSession
*p
)
233 /* for now just send a packet at a time */
235 int count
=read(p
->current_fd
, buffer
, 2048);
238 icq_Packet
*p2
=icq_TCPCreateFile06Packet(count
, buffer
);
239 icq_TCPLinkSend(p
->tcplink
, p2
);
240 p
->total_transferred_bytes
+=count
;
241 p
->current_file_progress
+=count
;
242 icq_FileSessionSetStatus(p
, FILE_STATUS_SENDING
);
244 invoke_callback(p
->icqlink
, icq_FileNotify
)(p
, FILE_NOTIFY_DATAPACKET
,
248 /* done transmitting if read returns less that 2048 bytes */
250 icq_FileSessionClose(p
);
257 void icq_FileSessionSetSpeed(icq_FileSession
*p
, int speed
)
259 icq_Packet
*packet
=icq_TCPCreateFile05Packet(speed
);
261 icq_TCPLinkSend(p
->tcplink
, packet
);
264 void icq_FileSessionClose(icq_FileSession
*p
)
266 icq_TCPLink
*plink
=p
->tcplink
;
268 /* TODO: handle closing already unallocated filesession? */
270 /* if we're attached to a tcplink, unattach so the link doesn't try
271 * to close us, and then close the tcplink */
275 icq_TCPLinkClose(plink
);
278 icq_ListRemove(p
->icqlink
->d
->icq_FileSessions
, p
);
279 icq_FileSessionDelete(p
);
282 void icq_FileSessionSetWorkingDir(icq_FileSession
*p
, const char *dir
)
284 int length
= sizeof(p
->working_dir
);
285 strncpy(p
->working_dir
, dir
, length
);
286 p
->working_dir
[length
-1]='\0';
289 void icq_FileSessionSetFiles(icq_FileSession
*p
, char **files
)