Tue, 28 Nov 2000 02:22:42 +0000
[gaim-migrate @ 1162]
icq. whoop de doo
| 1152 | 1 | #include <stdlib.h> |
| 2 | #include <fcntl.h> | |
| 3 | #include <stdio.h> | |
| 4 | #include <string.h> | |
| 5 | #include <sys/stat.h> | |
| 6 | ||
| 7 | #ifdef _MSVC_ | |
| 8 | #include <io.h> | |
| 9 | #define open _open | |
| 10 | #define close _close | |
| 11 | #define read _read | |
| 12 | #define write _write | |
| 13 | #endif | |
| 14 | ||
| 15 | #include "filesession.h" | |
| 16 | #include "list.h" | |
| 17 | #include "icqpacket.h" | |
| 18 | #include "stdpackets.h" | |
| 19 | ||
| 20 | icq_FileSession *icq_FileSessionNew(ICQLINK *icqlink) | |
| 21 | { | |
| 22 | icq_FileSession *p=(icq_FileSession *)malloc(sizeof(icq_FileSession)); | |
| 23 | ||
| 24 | if (p) | |
| 25 | { | |
| 26 | p->status=0; | |
| 27 | p->id=0L; | |
| 28 | p->icqlink=icqlink; | |
| 29 | p->current_fd=-1; | |
| 30 | p->current_file_num=0; | |
| 31 | p->current_file_progress=0; | |
| 32 | p->current_file_size=0; | |
| 33 | p->files=0L; | |
| 34 | p->current_speed=100; | |
| 35 | p->total_bytes=0; | |
| 36 | p->total_files=0; | |
| 37 | p->total_transferred_bytes=0; | |
| 38 | p->working_dir[0]=0; | |
| 39 | list_insert(icqlink->icq_FileSessions, 0, p); | |
| 40 | } | |
| 41 | ||
| 42 | return p; | |
| 43 | } | |
| 44 | ||
| 45 | void icq_FileSessionDelete(void *pv) | |
| 46 | { | |
| 47 | icq_FileSession *p=(icq_FileSession *)pv; | |
| 48 | ||
| 49 | if(p->files) { | |
| 50 | char **p2=p->files; | |
| 51 | while(*p2) | |
| 52 | free(*(p2++)); | |
| 53 | free(p->files); | |
| 54 | } | |
| 55 | ||
| 56 | if (p->current_fd > -1 ) { | |
| 57 | close(p->current_fd); | |
| 58 | p->current_fd=-1; | |
| 59 | } | |
| 60 | ||
| 61 | free(p); | |
| 62 | } | |
| 63 | ||
| 64 | int _icq_FindFileSession(void *p, va_list data) | |
| 65 | { | |
| 66 | icq_FileSession *psession=(icq_FileSession *)p; | |
| 67 | DWORD uin=va_arg(data, DWORD); | |
| 68 | unsigned long id=va_arg(data, unsigned long); | |
| 69 | ||
| 70 | return (psession->remote_uin == uin) && ( id ? (psession->id == id) : 1 ); | |
| 71 | ||
| 72 | } | |
| 73 | ||
| 74 | icq_FileSession *icq_FindFileSession(ICQLINK *icqlink, DWORD uin, | |
| 75 | unsigned long id) | |
| 76 | { | |
| 77 | return list_traverse(icqlink->icq_FileSessions, _icq_FindFileSession, | |
| 78 | uin, id); | |
| 79 | } | |
| 80 | ||
| 81 | void icq_FileSessionSetStatus(icq_FileSession *p, int status) | |
| 82 | { | |
| 83 | if(status!=p->status) | |
| 84 | { | |
| 85 | p->status=status; | |
| 86 | if(p->id && p->icqlink->icq_RequestNotify) | |
| 87 | (*p->icqlink->icq_RequestNotify)(p->icqlink, p->id, ICQ_NOTIFY_FILE, | |
| 88 | status, 0); | |
| 89 | } | |
| 90 | } | |
| 91 | ||
| 92 | void icq_FileSessionSetHandle(icq_FileSession *p, const char *handle) | |
| 93 | { | |
| 94 | strncpy(p->remote_handle, handle, 64); | |
| 95 | } | |
| 96 | ||
| 97 | void icq_FileSessionSetCurrentFile(icq_FileSession *p, const char *filename) | |
| 98 | { | |
| 99 | struct stat file_status; | |
| 100 | char file[1024]; | |
| 101 | ||
| 102 | strcpy(file, p->working_dir); | |
| 103 | strcat(file, filename); | |
| 104 | ||
| 105 | if (p->current_fd>-1) { | |
| 106 | close(p->current_fd); | |
| 107 | p->current_fd=-1; | |
| 108 | } | |
| 109 | ||
| 110 | strncpy(p->current_file, file, 64); | |
| 111 | p->current_file_progress=0; | |
| 112 | ||
| 113 | /* does the file already exist? */ | |
| 114 | if (stat(file, &file_status)==0) { | |
| 115 | p->current_file_progress=file_status.st_size; | |
| 116 | p->total_transferred_bytes+=file_status.st_size; | |
| 117 | p->current_fd=open(file, O_WRONLY | O_APPEND); | |
| 118 | } else { | |
| 119 | #ifdef _WIN32 | |
| 120 | p->current_fd=open(file, O_WRONLY | O_CREAT); | |
| 121 | #else | |
| 122 | p->current_fd=open(file, O_WRONLY | O_CREAT, S_IRWXU); | |
| 123 | #endif | |
| 124 | } | |
| 125 | ||
| 126 | /* make sure we have a valid filehandle */ | |
| 127 | if (p->current_fd == -1) | |
| 128 | perror("couldn't open file: "); | |
| 129 | ||
| 130 | } | |
| 131 | ||
| 132 | void icq_FileSessionPrepareNextFile(icq_FileSession *p) | |
| 133 | { | |
| 134 | int i=0; | |
| 135 | char **files=p->files; | |
| 136 | ||
| 137 | p->current_file_num++; | |
| 138 | ||
| 139 | while(*files) { | |
| 140 | i++; | |
| 141 | if(i==p->current_file_num) | |
| 142 | break; | |
| 143 | else | |
| 144 | files++; | |
| 145 | } | |
| 146 | ||
| 147 | if(*files) { | |
| 148 | struct stat file_status; | |
| 149 | ||
| 150 | if (p->current_fd>-1) { | |
| 151 | close(p->current_fd); | |
| 152 | p->current_fd=-1; | |
| 153 | } | |
| 154 | ||
| 155 | if (stat(*files, &file_status)==0) { | |
| 156 | char *basename=*files; | |
| 157 | char *pos=strrchr(basename, '/'); | |
| 158 | if(pos) basename=pos+1; | |
| 159 | strncpy(p->current_file, basename, 64); | |
| 160 | p->current_file_progress=0; | |
| 161 | p->current_file_size=file_status.st_size; | |
| 162 | p->current_fd=open(*files, O_RDONLY); | |
| 163 | } | |
| 164 | ||
| 165 | /* make sure we have a valid filehandle */ | |
| 166 | if (p->current_fd == -1) | |
| 167 | perror("couldn't open file: "); | |
| 168 | } | |
| 169 | } | |
| 170 | ||
| 171 | void icq_FileSessionSendData(icq_FileSession *p) | |
| 172 | { | |
| 173 | /* for now just send a packet at a time */ | |
| 174 | char buffer[2048]; | |
| 175 | int count=read(p->current_fd, buffer, 2048); | |
| 176 | ||
| 177 | if(count>0) { | |
| 178 | icq_Packet *p2=icq_TCPCreateFile06Packet(count, buffer); | |
| 179 | icq_TCPLinkSend(p->tcplink, p2); | |
| 180 | p->total_transferred_bytes+=count; | |
| 181 | p->current_file_progress+=count; | |
| 182 | icq_FileSessionSetStatus(p, FILE_STATUS_SENDING); | |
| 183 | ||
| 184 | if (p->icqlink->icq_RequestNotify) | |
| 185 | (*p->icqlink->icq_RequestNotify)(p->icqlink, p->id, | |
| 186 | ICQ_NOTIFY_FILEDATA, count, NULL); | |
| 187 | } | |
| 188 | ||
| 189 | /* done transmitting if read returns less that 2048 bytes */ | |
| 190 | if(count<2048) | |
| 191 | icq_FileSessionClose(p); | |
| 192 | ||
| 193 | return; | |
| 194 | } | |
| 195 | ||
| 196 | /* public */ | |
| 197 | ||
| 198 | void icq_FileSessionSetSpeed(icq_FileSession *p, int speed) | |
| 199 | { | |
| 200 | icq_Packet *packet=icq_TCPCreateFile05Packet(speed); | |
| 201 | ||
| 202 | icq_TCPLinkSend(p->tcplink, packet); | |
| 203 | } | |
| 204 | ||
| 205 | void icq_FileSessionClose(icq_FileSession *p) | |
| 206 | { | |
| 207 | icq_TCPLink *plink=p->tcplink; | |
| 208 | ||
| 209 | /* TODO: handle closing already unallocated filesession? */ | |
| 210 | ||
| 211 | /* if we're attached to a tcplink, unattach so the link doesn't try | |
| 212 | * to close us, and then close the tcplink */ | |
| 213 | if (plink) | |
| 214 | { | |
| 215 | plink->session=0L; | |
| 216 | icq_TCPLinkClose(plink); | |
| 217 | } | |
| 218 | ||
| 219 | icq_FileSessionDelete(p); | |
| 220 | ||
| 221 | list_remove(p->icqlink->icq_FileSessions, p); | |
| 222 | } | |
| 223 | ||
| 224 | void icq_FileSessionSetWorkingDir(icq_FileSession *p, const char *dir) | |
| 225 | { | |
| 226 | strncpy(p->working_dir, dir, 512); | |
| 227 | } | |
| 228 | ||
| 229 | void icq_FileSessionSetFiles(icq_FileSession *p, char **files) | |
| 230 | { | |
| 231 | p->files=files; | |
| 232 | } | |
| 233 |