Changeset 5ebff60 for protocols/msn/invitation.c
- Timestamp:
- 2015-02-20T22:50:54Z (10 years ago)
- Branches:
- master
- Children:
- 0b9daac, 3d45471, 7733b8c
- Parents:
- af359b4
- git-author:
- Indent <please@…> (19-02-15 05:47:20)
- git-committer:
- dequis <dx@…> (20-02-15 22:50:54)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
protocols/msn/invitation.c
raf359b4 r5ebff60 13 13 the Free Software Foundation; either version 2 of the License, or 14 14 (at your option) any later version. 15 15 16 16 This program is distributed in the hope that it will be useful, 17 17 but WITHOUT ANY WARRANTY; without even the implied warranty of 18 18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 19 GNU General Public License for more details. 20 20 21 21 You should have received a copy of the GNU General Public License with 22 22 the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; … … 33 33 #undef debug 34 34 #endif 35 #define debug(msg ...) log_message( LOGLVL_INFO, msg)36 37 static void msn_ftp_free( file_transfer_t *file);38 static void msn_ftpr_accept( file_transfer_t *file);39 static void msn_ftp_finished( file_transfer_t *file);40 static void msn_ftp_canceled( file_transfer_t *file, char *reason);41 static gboolean msn_ftpr_write_request( file_transfer_t *file);42 43 static gboolean msn_ftp_connected( gpointer data, gint fd, b_input_condition cond);44 static gboolean msn_ftp_read( gpointer data, gint fd, b_input_condition cond);45 gboolean msn_ftps_write( file_transfer_t *file, char *buffer, unsigned int len);35 #define debug(msg ...) log_message(LOGLVL_INFO, msg) 36 37 static void msn_ftp_free(file_transfer_t *file); 38 static void msn_ftpr_accept(file_transfer_t *file); 39 static void msn_ftp_finished(file_transfer_t *file); 40 static void msn_ftp_canceled(file_transfer_t *file, char *reason); 41 static gboolean msn_ftpr_write_request(file_transfer_t *file); 42 43 static gboolean msn_ftp_connected(gpointer data, gint fd, b_input_condition cond); 44 static gboolean msn_ftp_read(gpointer data, gint fd, b_input_condition cond); 45 gboolean msn_ftps_write(file_transfer_t *file, char *buffer, unsigned int len); 46 46 47 47 /* 48 48 * Vararg wrapper for imcb_file_canceled(). 49 49 */ 50 gboolean msn_ftp_abort( file_transfer_t *file, char *format, ... ) 51 { 52 va_list params; 53 va_start( params, format ); 54 char error[128]; 55 56 if( vsnprintf( error, 128, format, params ) < 0 ) 57 sprintf( error, "internal error parsing error string (BUG)" ); 58 va_end( params ); 59 imcb_file_canceled( file, error ); 50 gboolean msn_ftp_abort(file_transfer_t *file, char *format, ...) 51 { 52 va_list params; 53 54 va_start(params, format); 55 char error[128]; 56 57 if (vsnprintf(error, 128, format, params) < 0) { 58 sprintf(error, "internal error parsing error string (BUG)"); 59 } 60 va_end(params); 61 imcb_file_canceled(file, error); 60 62 return FALSE; 61 63 } … … 63 65 /* very useful */ 64 66 #define ASSERTSOCKOP(op, msg) \ 65 if ( (op) == -1 )\66 return msn_ftp_abort( file , msg ": %s", strerror( errno ) );67 68 void msn_ftp_invitation_cmd( 69 char *trailer)70 { 71 struct msn_message *m = g_new0( struct msn_message, 1);72 73 m->text = g_strdup_printf( 74 75 76 77 78 79 80 81 82 m->who = g_strdup( who);83 84 msn_sb_write_msg( ic, m);85 } 86 87 void msn_ftp_cancel_invite( struct im_connection *ic, char *who, int cookie, char *code)67 if ((op) == -1) { \ 68 return msn_ftp_abort(file, msg ": %s", strerror(errno)); } 69 70 void msn_ftp_invitation_cmd(struct im_connection *ic, char *who, int cookie, char *icmd, 71 char *trailer) 72 { 73 struct msn_message *m = g_new0(struct msn_message, 1); 74 75 m->text = g_strdup_printf("%s" 76 "Invitation-Command: %s\r\n" 77 "Invitation-Cookie: %u\r\n" 78 "%s", 79 MSN_INVITE_HEADERS, 80 icmd, 81 cookie, 82 trailer); 83 84 m->who = g_strdup(who); 85 86 msn_sb_write_msg(ic, m); 87 } 88 89 void msn_ftp_cancel_invite(struct im_connection *ic, char *who, int cookie, char *code) 88 90 { 89 91 char buf[64]; 90 92 91 g_snprintf( buf, sizeof( buf ), "Cancel-Code: %s\r\n", code);92 msn_ftp_invitation_cmd( ic, who, cookie, "CANCEL", buf);93 } 94 95 void msn_ftp_transfer_request( struct im_connection *ic, file_transfer_t *file, char *who)96 { 97 unsigned int cookie = time( NULL );/* TODO: randomize */93 g_snprintf(buf, sizeof(buf), "Cancel-Code: %s\r\n", code); 94 msn_ftp_invitation_cmd(ic, who, cookie, "CANCEL", buf); 95 } 96 97 void msn_ftp_transfer_request(struct im_connection *ic, file_transfer_t *file, char *who) 98 { 99 unsigned int cookie = time(NULL); /* TODO: randomize */ 98 100 char buf[2048]; 99 101 100 msn_filetransfer_t *msn_file = g_new0( msn_filetransfer_t, 1 ); 102 msn_filetransfer_t *msn_file = g_new0(msn_filetransfer_t, 1); 103 101 104 file->data = msn_file; 102 105 file->free = msn_ftp_free; … … 105 108 msn_file->md = ic->proto_data; 106 109 msn_file->invite_cookie = cookie; 107 msn_file->handle = g_strdup( who);110 msn_file->handle = g_strdup(who); 108 111 msn_file->dcc = file; 109 msn_file->md->filetransfers = g_slist_prepend( msn_file->md->filetransfers, msn_file->dcc);112 msn_file->md->filetransfers = g_slist_prepend(msn_file->md->filetransfers, msn_file->dcc); 110 113 msn_file->fd = -1; 111 114 msn_file->sbufpos = 3; 112 115 113 g_snprintf( buf, sizeof( buf ),114 115 116 117 118 119 120 121 msn_ftp_invitation_cmd( msn_file->md->ic, msn_file->handle, cookie, "INVITE", buf);122 123 imcb_file_recv_start( file);124 } 125 126 void msn_invitation_invite( struct msn_switchboard *sb, char *handle, unsigned int cookie, char *body, int blen)127 { 128 char *itype = msn_findheader( body, "Application-GUID:", blen);116 g_snprintf(buf, sizeof(buf), 117 "Application-Name: File Transfer\r\n" 118 "Application-GUID: {5D3E02AB-6190-11d3-BBBB-00C04F795683}\r\n" 119 "Application-File: %s\r\n" 120 "Application-FileSize: %zd\r\n", 121 file->file_name, 122 file->file_size); 123 124 msn_ftp_invitation_cmd(msn_file->md->ic, msn_file->handle, cookie, "INVITE", buf); 125 126 imcb_file_recv_start(file); 127 } 128 129 void msn_invitation_invite(struct msn_switchboard *sb, char *handle, unsigned int cookie, char *body, int blen) 130 { 131 char *itype = msn_findheader(body, "Application-GUID:", blen); 129 132 char *name, *size, *invitecookie, *reject = NULL; 130 133 user_t *u; 131 134 size_t isize; 132 135 file_transfer_t *file; 133 134 if ( !itype || strcmp( itype, "{5D3E02AB-6190-11d3-BBBB-00C04F795683}" ) != 0) {136 137 if (!itype || strcmp(itype, "{5D3E02AB-6190-11d3-BBBB-00C04F795683}") != 0) { 135 138 /* Don't know what that is - don't care */ 136 char *iname = msn_findheader( body, "Application-Name:", blen);137 imcb_log( 138 itype ? : "with no GUID", iname ? iname : "no application name", handle);139 g_free( iname);139 char *iname = msn_findheader(body, "Application-Name:", blen); 140 imcb_log(sb->ic, "Received unknown MSN invitation %s (%s) from %s", 141 itype ? : "with no GUID", iname ? iname : "no application name", handle); 142 g_free(iname); 140 143 reject = "REJECT_NOT_INSTALLED"; 141 } else if ( 142 !( name = msn_findheader( body, "Application-File:", blen )) ||143 !( size = msn_findheader( body, "Application-FileSize:", blen )) ||144 !( invitecookie = msn_findheader(body, "Invitation-Cookie:", blen)) ||145 !( isize = atoll( size ) ) ) {146 imcb_log( 147 148 handle, name, size, invitecookie);144 } else if ( 145 !(name = msn_findheader(body, "Application-File:", blen)) || 146 !(size = msn_findheader(body, "Application-FileSize:", blen)) || 147 !(invitecookie = msn_findheader(body, "Invitation-Cookie:", blen)) || 148 !(isize = atoll(size))) { 149 imcb_log(sb->ic, "Received corrupted transfer request from %s" 150 "(name=%s, size=%s, invitecookie=%s)", 151 handle, name, size, invitecookie); 149 152 reject = "REJECT"; 150 } else if ( !( u = user_findhandle( sb->ic, handle ) )) {151 imcb_log( 152 "is not in contact list", handle);153 } else if (!(u = user_findhandle(sb->ic, handle))) { 154 imcb_log(sb->ic, "Error in parsing transfer request, User '%s'" 155 "is not in contact list", handle); 153 156 reject = "REJECT"; 154 } else if ( !( file = imcb_file_send_start( sb->ic, handle, name, isize ) )) {155 imcb_log( 156 handle, name);157 } else if (!(file = imcb_file_send_start(sb->ic, handle, name, isize))) { 158 imcb_log(sb->ic, "Error initiating transfer for request from %s for %s", 159 handle, name); 157 160 reject = "REJECT"; 158 161 } else { 159 msn_filetransfer_t *msn_file = g_new0( msn_filetransfer_t, 1);162 msn_filetransfer_t *msn_file = g_new0(msn_filetransfer_t, 1); 160 163 file->data = msn_file; 161 164 file->accept = msn_ftpr_accept; … … 166 169 msn_file->md = sb->ic->proto_data; 167 170 msn_file->invite_cookie = cookie; 168 msn_file->handle = g_strdup( handle);171 msn_file->handle = g_strdup(handle); 169 172 msn_file->dcc = file; 170 msn_file->md->filetransfers = g_slist_prepend( msn_file->md->filetransfers, msn_file->dcc);173 msn_file->md->filetransfers = g_slist_prepend(msn_file->md->filetransfers, msn_file->dcc); 171 174 msn_file->fd = -1; 172 175 } 173 176 174 if( reject ) 175 msn_ftp_cancel_invite( sb->ic, sb->who, cookie, reject ); 176 177 g_free( name ); 178 g_free( size ); 179 g_free( invitecookie ); 180 g_free( itype ); 181 } 182 183 msn_filetransfer_t* msn_find_filetransfer( struct msn_data *md, unsigned int cookie, char *handle ) 177 if (reject) { 178 msn_ftp_cancel_invite(sb->ic, sb->who, cookie, reject); 179 } 180 181 g_free(name); 182 g_free(size); 183 g_free(invitecookie); 184 g_free(itype); 185 } 186 187 msn_filetransfer_t* msn_find_filetransfer(struct msn_data *md, unsigned int cookie, char *handle) 184 188 { 185 189 GSList *l; 186 187 for ( l = md->filetransfers; l; l = l->next) {188 msn_filetransfer_t *file = ( (file_transfer_t*) l->data)->data;189 if ( file->invite_cookie == cookie && strcmp( handle, file->handle ) == 0) {190 191 for (l = md->filetransfers; l; l = l->next) { 192 msn_filetransfer_t *file = ((file_transfer_t *) l->data)->data; 193 if (file->invite_cookie == cookie && strcmp(handle, file->handle) == 0) { 190 194 return file; 191 195 } … … 194 198 } 195 199 196 gboolean msn_ftps_connected( gpointer data, gint fd, b_input_condition cond)200 gboolean msn_ftps_connected(gpointer data, gint fd, b_input_condition cond) 197 201 { 198 202 file_transfer_t *file = data; 199 203 msn_filetransfer_t *msn_file = file->data; 200 204 struct sockaddr_storage clt_addr; 201 socklen_t ssize = sizeof( clt_addr);202 203 debug( "Connected to MSNFTP client");204 205 ASSERTSOCKOP( msn_file->fd = accept( fd, (struct sockaddr *) &clt_addr, &ssize ), "Accepting connection");206 207 closesocket( fd);205 socklen_t ssize = sizeof(clt_addr); 206 207 debug("Connected to MSNFTP client"); 208 209 ASSERTSOCKOP(msn_file->fd = accept(fd, (struct sockaddr *) &clt_addr, &ssize), "Accepting connection"); 210 211 closesocket(fd); 208 212 fd = msn_file->fd; 209 sock_make_nonblocking( fd);210 211 msn_file->r_event_id = b_input_add( fd, B_EV_IO_READ, msn_ftp_read, file);213 sock_make_nonblocking(fd); 214 215 msn_file->r_event_id = b_input_add(fd, B_EV_IO_READ, msn_ftp_read, file); 212 216 213 217 return FALSE; 214 218 } 215 219 216 void msn_invitations_accept( msn_filetransfer_t *msn_file, struct msn_switchboard *sb, char *handle, unsigned int cookie, char *body, int blen ) 220 void msn_invitations_accept(msn_filetransfer_t *msn_file, struct msn_switchboard *sb, char *handle, unsigned int cookie, 221 char *body, int blen) 217 222 { 218 223 file_transfer_t *file = msn_file->dcc; 219 224 char buf[1024]; 220 unsigned int acookie = time ( NULL);221 char host[HOST_NAME_MAX +1];225 unsigned int acookie = time(NULL); 226 char host[HOST_NAME_MAX + 1]; 222 227 char port[6]; 223 228 char *errmsg; … … 225 230 msn_file->auth_cookie = acookie; 226 231 227 if( ( msn_file->fd = ft_listen( NULL, host, port, FALSE, &errmsg ) ) == -1 ) { 228 msn_ftp_abort( file, "Failed to listen locally, check your ft_listen setting in bitlbee.conf: %s", errmsg ); 232 if ((msn_file->fd = ft_listen(NULL, host, port, FALSE, &errmsg)) == -1) { 233 msn_ftp_abort(file, "Failed to listen locally, check your ft_listen setting in bitlbee.conf: %s", 234 errmsg); 229 235 return; 230 236 } 231 237 232 msn_file->r_event_id = b_input_add( msn_file->fd, B_EV_IO_READ, msn_ftps_connected, file ); 233 234 g_snprintf( buf, sizeof( buf ), 235 "IP-Address: %s\r\n" 236 "Port: %s\r\n" 237 "AuthCookie: %d\r\n" 238 "Launch-Application: FALSE\r\n" 239 "Request-Data: IP-Address:\r\n\r\n", 240 host, 241 port, 242 msn_file->auth_cookie ); 243 244 msn_ftp_invitation_cmd( msn_file->md->ic, handle, msn_file->invite_cookie, "ACCEPT", buf ); 245 } 246 247 void msn_invitationr_accept( msn_filetransfer_t *msn_file, struct msn_switchboard *sb, char *handle, unsigned int cookie, char *body, int blen ) { 238 msn_file->r_event_id = b_input_add(msn_file->fd, B_EV_IO_READ, msn_ftps_connected, file); 239 240 g_snprintf(buf, sizeof(buf), 241 "IP-Address: %s\r\n" 242 "Port: %s\r\n" 243 "AuthCookie: %d\r\n" 244 "Launch-Application: FALSE\r\n" 245 "Request-Data: IP-Address:\r\n\r\n", 246 host, 247 port, 248 msn_file->auth_cookie); 249 250 msn_ftp_invitation_cmd(msn_file->md->ic, handle, msn_file->invite_cookie, "ACCEPT", buf); 251 } 252 253 void msn_invitationr_accept(msn_filetransfer_t *msn_file, struct msn_switchboard *sb, char *handle, unsigned int cookie, 254 char *body, int blen) 255 { 248 256 file_transfer_t *file = msn_file->dcc; 249 257 char *authcookie, *ip, *port; 250 258 251 if( !( authcookie = msn_findheader( body, "AuthCookie:", blen ) ) || 252 !( ip = msn_findheader( body, "IP-Address:", blen ) ) || 253 !( port = msn_findheader( body, "Port:", blen ) ) ) { 254 msn_ftp_abort( file, "Received invalid accept reply" ); 255 } else if( 256 ( msn_file->fd = proxy_connect( ip, atoi( port ), msn_ftp_connected, file ) ) 257 < 0 ) { 258 msn_ftp_abort( file, "Error connecting to MSN client" ); 259 } else 260 msn_file->auth_cookie = strtoul( authcookie, NULL, 10 ); 261 262 g_free( authcookie ); 263 g_free( ip ); 264 g_free( port ); 265 } 266 267 void msn_invitation_accept( struct msn_switchboard *sb, char *handle, unsigned int cookie, char *body, int blen ) 268 { 269 msn_filetransfer_t *msn_file = msn_find_filetransfer( sb->ic->proto_data, cookie, handle ); 259 if (!(authcookie = msn_findheader(body, "AuthCookie:", blen)) || 260 !(ip = msn_findheader(body, "IP-Address:", blen)) || 261 !(port = msn_findheader(body, "Port:", blen))) { 262 msn_ftp_abort(file, "Received invalid accept reply"); 263 } else if ( 264 (msn_file->fd = proxy_connect(ip, atoi(port), msn_ftp_connected, file)) 265 < 0) { 266 msn_ftp_abort(file, "Error connecting to MSN client"); 267 } else { 268 msn_file->auth_cookie = strtoul(authcookie, NULL, 10); 269 } 270 271 g_free(authcookie); 272 g_free(ip); 273 g_free(port); 274 } 275 276 void msn_invitation_accept(struct msn_switchboard *sb, char *handle, unsigned int cookie, char *body, int blen) 277 { 278 msn_filetransfer_t *msn_file = msn_find_filetransfer(sb->ic->proto_data, cookie, handle); 270 279 file_transfer_t *file = msn_file ? msn_file->dcc : NULL; 271 272 if( !msn_file ) 273 imcb_log( sb->ic, "Received invitation ACCEPT message for unknown invitation (already aborted?)" ); 274 else if( file->sending ) 275 msn_invitations_accept( msn_file, sb, handle, cookie, body, blen ); 276 else 277 msn_invitationr_accept( msn_file, sb, handle, cookie, body, blen ); 278 } 279 280 void msn_invitation_cancel( struct msn_switchboard *sb, char *handle, unsigned int cookie, char *body, int blen ) 281 { 282 msn_filetransfer_t *msn_file = msn_find_filetransfer( sb->ic->proto_data, cookie, handle ); 283 284 if( !msn_file ) 285 imcb_log( sb->ic, "Received invitation CANCEL message for unknown invitation (already aborted?)" ); 286 else 287 msn_ftp_abort( msn_file->dcc, msn_findheader( body, "Cancel-Code:", blen ) ); 288 } 289 290 int msn_ftp_write( file_transfer_t *file, char *format, ... ) 280 281 if (!msn_file) { 282 imcb_log(sb->ic, "Received invitation ACCEPT message for unknown invitation (already aborted?)"); 283 } else if (file->sending) { 284 msn_invitations_accept(msn_file, sb, handle, cookie, body, blen); 285 } else { 286 msn_invitationr_accept(msn_file, sb, handle, cookie, body, blen); 287 } 288 } 289 290 void msn_invitation_cancel(struct msn_switchboard *sb, char *handle, unsigned int cookie, char *body, int blen) 291 { 292 msn_filetransfer_t *msn_file = msn_find_filetransfer(sb->ic->proto_data, cookie, handle); 293 294 if (!msn_file) { 295 imcb_log(sb->ic, "Received invitation CANCEL message for unknown invitation (already aborted?)"); 296 } else { 297 msn_ftp_abort(msn_file->dcc, msn_findheader(body, "Cancel-Code:", blen)); 298 } 299 } 300 301 int msn_ftp_write(file_transfer_t *file, char *format, ...) 291 302 { 292 303 msn_filetransfer_t *msn_file = file->data; … … 294 305 int st; 295 306 char *s; 296 297 va_start( params, format ); 298 s = g_strdup_vprintf( format, params ); 299 va_end( params ); 300 301 st = write( msn_file->fd, s, strlen( s ) ); 302 if( st != strlen( s ) ) 303 return msn_ftp_abort( file, "Error sending data over MSNFTP connection: %s", 304 strerror( errno ) ); 305 306 g_free( s ); 307 308 va_start(params, format); 309 s = g_strdup_vprintf(format, params); 310 va_end(params); 311 312 st = write(msn_file->fd, s, strlen(s)); 313 if (st != strlen(s)) { 314 return msn_ftp_abort(file, "Error sending data over MSNFTP connection: %s", 315 strerror(errno)); 316 } 317 318 g_free(s); 307 319 return 1; 308 320 } 309 321 310 gboolean msn_ftp_connected( gpointer data, gint fd, b_input_condition cond)322 gboolean msn_ftp_connected(gpointer data, gint fd, b_input_condition cond) 311 323 { 312 324 file_transfer_t *file = data; 313 325 msn_filetransfer_t *msn_file = file->data; 314 315 debug( "Connected to MSNFTP server, starting authentication");316 if ( !msn_ftp_write( file, "VER MSNFTP\r\n" ) )326 327 debug("Connected to MSNFTP server, starting authentication"); 328 if (!msn_ftp_write(file, "VER MSNFTP\r\n")) { 317 329 return FALSE; 318 319 sock_make_nonblocking( msn_file->fd ); 320 msn_file->r_event_id = b_input_add( msn_file->fd, B_EV_IO_READ, msn_ftp_read, file ); 321 330 } 331 332 sock_make_nonblocking(msn_file->fd); 333 msn_file->r_event_id = b_input_add(msn_file->fd, B_EV_IO_READ, msn_ftp_read, file); 334 322 335 return FALSE; 323 336 } 324 337 325 gboolean msn_ftp_handle_command( file_transfer_t *file, char* line)326 { 327 msn_filetransfer_t *msn_file = file->data; 328 char **cmd = msn_linesplit( line);338 gboolean msn_ftp_handle_command(file_transfer_t *file, char* line) 339 { 340 msn_filetransfer_t *msn_file = file->data; 341 char **cmd = msn_linesplit(line); 329 342 int count = 0; 330 if( cmd[0] ) while( cmd[++count] ); 331 332 if( count < 1 ) 333 return msn_ftp_abort( file, "Missing command in MSNFTP communication" ); 334 335 if( strcmp( cmd[0], "VER" ) == 0 ) { 336 if( strcmp( cmd[1], "MSNFTP" ) != 0 ) 337 return msn_ftp_abort( file, "Unsupported filetransfer protocol: %s", cmd[1] ); 338 if( file->sending ) 339 msn_ftp_write( file, "VER MSNFTP\r\n" ); 340 else 341 msn_ftp_write( file, "USR %s %u\r\n", msn_file->md->ic->acc->user, msn_file->auth_cookie ); 342 } else if( strcmp( cmd[0], "FIL" ) == 0 ) { 343 if( strtoul( cmd[1], NULL, 10 ) != file->file_size ) 344 return msn_ftp_abort( file, "FIL reply contains a different file size than the size in the invitation" ); 345 msn_ftp_write( file, "TFR\r\n" ); 343 344 if (cmd[0]) { 345 while (cmd[++count]) { 346 ; 347 } 348 } 349 350 if (count < 1) { 351 return msn_ftp_abort(file, "Missing command in MSNFTP communication"); 352 } 353 354 if (strcmp(cmd[0], "VER") == 0) { 355 if (strcmp(cmd[1], "MSNFTP") != 0) { 356 return msn_ftp_abort(file, "Unsupported filetransfer protocol: %s", cmd[1]); 357 } 358 if (file->sending) { 359 msn_ftp_write(file, "VER MSNFTP\r\n"); 360 } else { 361 msn_ftp_write(file, "USR %s %u\r\n", msn_file->md->ic->acc->user, msn_file->auth_cookie); 362 } 363 } else if (strcmp(cmd[0], "FIL") == 0) { 364 if (strtoul(cmd[1], NULL, 10) != file->file_size) { 365 return msn_ftp_abort(file, 366 "FIL reply contains a different file size than the size in the invitation"); 367 } 368 msn_ftp_write(file, "TFR\r\n"); 346 369 msn_file->status |= MSN_TRANSFER_RECEIVING; 347 } else if( strcmp( cmd[0], "USR" ) == 0 ) { 348 if( ( strcmp( cmd[1], msn_file->handle ) != 0 ) || 349 ( strtoul( cmd[2], NULL, 10 ) != msn_file->auth_cookie ) ) 350 msn_ftp_abort( file, "Authentication failed. " 351 "Expected handle: %s (got %s), cookie: %u (got %s)", 352 msn_file->handle, cmd[1], 353 msn_file->auth_cookie, cmd[2] ); 354 msn_ftp_write( file, "FIL %zu\r\n", file->file_size); 355 } else if( strcmp( cmd[0], "TFR" ) == 0 ) { 356 file->write_request( file ); 357 } else if( strcmp( cmd[0], "BYE" ) == 0 ) { 370 } else if (strcmp(cmd[0], "USR") == 0) { 371 if ((strcmp(cmd[1], msn_file->handle) != 0) || 372 (strtoul(cmd[2], NULL, 10) != msn_file->auth_cookie)) { 373 msn_ftp_abort(file, "Authentication failed. " 374 "Expected handle: %s (got %s), cookie: %u (got %s)", 375 msn_file->handle, cmd[1], 376 msn_file->auth_cookie, cmd[2]); 377 } 378 msn_ftp_write(file, "FIL %zu\r\n", file->file_size); 379 } else if (strcmp(cmd[0], "TFR") == 0) { 380 file->write_request(file); 381 } else if (strcmp(cmd[0], "BYE") == 0) { 358 382 unsigned int retcode = count > 1 ? atoi(cmd[1]) : 1; 359 383 360 if ( ( retcode==16777989 ) || ( retcode==16777987 ) )361 imcb_file_finished( file);362 else if( retcode==2147942405 )363 imcb_file_canceled( file, "Failure: receiver is out of disk space");364 else if( retcode==2164261682 )365 imcb_file_canceled( file, "Failure: receiver cancelled the transfer");366 else if( retcode==2164261683 )367 imcb_file_canceled( file, "Failure: sender has cancelled the transfer");368 else if( retcode==2164261694 )369 imcb_file_canceled( file, "Failure: connection is blocked");370 else {384 if ((retcode == 16777989) || (retcode == 16777987)) { 385 imcb_file_finished(file); 386 } else if (retcode == 2147942405) { 387 imcb_file_canceled(file, "Failure: receiver is out of disk space"); 388 } else if (retcode == 2164261682) { 389 imcb_file_canceled(file, "Failure: receiver cancelled the transfer"); 390 } else if (retcode == 2164261683) { 391 imcb_file_canceled(file, "Failure: sender has cancelled the transfer"); 392 } else if (retcode == 2164261694) { 393 imcb_file_canceled(file, "Failure: connection is blocked"); 394 } else { 371 395 char buf[128]; 372 396 373 sprintf( 374 imcb_file_canceled( file, buf);375 } 376 } else if ( strcmp( cmd[0], "CCL" ) == 0) {377 imcb_file_canceled( file, "Failure: receiver cancelled the transfer");378 } else { 379 msn_ftp_abort( file, "Received invalid command %s from msn client", cmd[0]);397 sprintf(buf, "Failure: unknown BYE code: %d", retcode); 398 imcb_file_canceled(file, buf); 399 } 400 } else if (strcmp(cmd[0], "CCL") == 0) { 401 imcb_file_canceled(file, "Failure: receiver cancelled the transfer"); 402 } else { 403 msn_ftp_abort(file, "Received invalid command %s from msn client", cmd[0]); 380 404 } 381 405 return TRUE; 382 406 } 383 407 384 gboolean msn_ftp_send( gpointer data, gint fd, b_input_condition cond)408 gboolean msn_ftp_send(gpointer data, gint fd, b_input_condition cond) 385 409 { 386 410 file_transfer_t *file = data; … … 389 413 msn_file->w_event_id = 0; 390 414 391 file->write_request( file);415 file->write_request(file); 392 416 393 417 return FALSE; … … 399 423 * This got a bit complicated because (at least) amsn expects packets of size 2045. 400 424 */ 401 gboolean msn_ftps_write( file_transfer_t *file, char *buffer, unsigned int len)402 { 403 msn_filetransfer_t *msn_file = file->data; 404 425 gboolean msn_ftps_write(file_transfer_t *file, char *buffer, unsigned int len) 426 { 427 msn_filetransfer_t *msn_file = file->data; 428 int ret, overflow; 405 429 406 430 /* what we can't send now */ … … 408 432 409 433 /* append what we can do the send buffer */ 410 memcpy( msn_file->sbuf + msn_file->sbufpos, buffer, MIN( len, MSNFTP_PSIZE - msn_file->sbufpos ));411 msn_file->sbufpos += MIN( len, MSNFTP_PSIZE - msn_file->sbufpos);434 memcpy(msn_file->sbuf + msn_file->sbufpos, buffer, MIN(len, MSNFTP_PSIZE - msn_file->sbufpos)); 435 msn_file->sbufpos += MIN(len, MSNFTP_PSIZE - msn_file->sbufpos); 412 436 413 437 /* if we don't have enough for a full packet and there's more wait for it */ 414 if( ( msn_file->sbufpos < MSNFTP_PSIZE ) && 415 ( msn_file->data_sent + msn_file->sbufpos - 3 < file->file_size ) ) { 416 if( !msn_file->w_event_id ) 417 msn_file->w_event_id = b_input_add( msn_file->fd, B_EV_IO_WRITE, msn_ftp_send, file ); 438 if ((msn_file->sbufpos < MSNFTP_PSIZE) && 439 (msn_file->data_sent + msn_file->sbufpos - 3 < file->file_size)) { 440 if (!msn_file->w_event_id) { 441 msn_file->w_event_id = b_input_add(msn_file->fd, B_EV_IO_WRITE, msn_ftp_send, file); 442 } 418 443 return TRUE; 419 444 } … … 422 447 423 448 msn_file->sbuf[0] = 0; 424 msn_file->sbuf[1] = ( msn_file->sbufpos - 3 ) & 0xff; 425 msn_file->sbuf[2] = ( ( msn_file->sbufpos - 3 ) >> 8 ) & 0xff; 426 427 ASSERTSOCKOP( ret = send( msn_file->fd, msn_file->sbuf, msn_file->sbufpos, 0 ), "Sending" ); 428 429 msn_file->data_sent += ret - 3; 430 431 /* TODO: this should really not be fatal */ 432 if( ret < msn_file->sbufpos ) 433 return msn_ftp_abort( file, "send() sent %d instead of %d (send buffer full!)", ret, msn_file->sbufpos ); 449 msn_file->sbuf[1] = (msn_file->sbufpos - 3) & 0xff; 450 msn_file->sbuf[2] = ((msn_file->sbufpos - 3) >> 8) & 0xff; 451 452 ASSERTSOCKOP(ret = send(msn_file->fd, msn_file->sbuf, msn_file->sbufpos, 0), "Sending"); 453 454 msn_file->data_sent += ret - 3; 455 456 /* TODO: this should really not be fatal */ 457 if (ret < msn_file->sbufpos) { 458 return msn_ftp_abort(file, "send() sent %d instead of %d (send buffer full!)", ret, msn_file->sbufpos); 459 } 434 460 435 461 msn_file->sbufpos = 3; 436 462 437 if ( overflow > 0) {438 while ( overflow > ( MSNFTP_PSIZE - 3 )) {439 if ( !msn_ftps_write( file, buffer + len - overflow, MSNFTP_PSIZE - 3 ) )463 if (overflow > 0) { 464 while (overflow > (MSNFTP_PSIZE - 3)) { 465 if (!msn_ftps_write(file, buffer + len - overflow, MSNFTP_PSIZE - 3)) { 440 466 return FALSE; 467 } 441 468 overflow -= MSNFTP_PSIZE - 3; 442 469 } 443 return msn_ftps_write( file, buffer + len - overflow, overflow);444 } 445 446 if ( msn_file->data_sent == file->file_size) {447 if ( msn_file->w_event_id) {448 b_event_remove( msn_file->w_event_id);470 return msn_ftps_write(file, buffer + len - overflow, overflow); 471 } 472 473 if (msn_file->data_sent == file->file_size) { 474 if (msn_file->w_event_id) { 475 b_event_remove(msn_file->w_event_id); 449 476 msn_file->w_event_id = 0; 450 477 } 451 478 } else { 452 479 /* we might already be listening if this is data from an overflow */ 453 if( !msn_file->w_event_id ) 454 msn_file->w_event_id = b_input_add( msn_file->fd, B_EV_IO_WRITE, msn_ftp_send, file ); 455 } 456 457 return TRUE; 480 if (!msn_file->w_event_id) { 481 msn_file->w_event_id = b_input_add(msn_file->fd, B_EV_IO_WRITE, msn_ftp_send, file); 482 } 483 } 484 485 return TRUE; 458 486 } 459 487 460 488 /* Binary part of the file transfer protocol */ 461 gboolean msn_ftpr_read( file_transfer_t *file )489 gboolean msn_ftpr_read(file_transfer_t *file) 462 490 { 463 491 msn_filetransfer_t *msn_file = file->data; … … 465 493 unsigned char buf[3]; 466 494 467 if ( msn_file->data_remaining) {495 if (msn_file->data_remaining) { 468 496 msn_file->r_event_id = 0; 469 497 470 ASSERTSOCKOP( st = read( msn_file->fd, file->buffer, MIN( sizeof( file->buffer ), msn_file->data_remaining ) ), "Receiving" ); 471 472 if( st == 0 ) 473 return msn_ftp_abort( file, "Remote end closed connection"); 498 ASSERTSOCKOP(st = read(msn_file->fd, file->buffer, MIN(sizeof(file->buffer), 499 msn_file->data_remaining)), "Receiving"); 500 501 if (st == 0) { 502 return msn_ftp_abort(file, "Remote end closed connection"); 503 } 474 504 475 505 msn_file->data_sent += st; … … 477 507 msn_file->data_remaining -= st; 478 508 479 file->write( file, file->buffer, st ); 480 481 if( msn_file->data_sent >= file->file_size ) 482 imcb_file_finished( file ); 509 file->write(file, file->buffer, st); 510 511 if (msn_file->data_sent >= file->file_size) { 512 imcb_file_finished(file); 513 } 483 514 484 515 return FALSE; 485 516 } else { 486 ASSERTSOCKOP( st = read( msn_file->fd, buf, 1 ), "Receiving");487 if ( st == 0) {488 return msn_ftp_abort( file, "read returned EOF while reading data header from msn client");489 } else if ( buf[0] == '\r' || buf[0] == '\n') {490 debug( "Discarding extraneous newline");491 } else if ( buf[0] != 0) {492 msn_ftp_abort( 517 ASSERTSOCKOP(st = read(msn_file->fd, buf, 1), "Receiving"); 518 if (st == 0) { 519 return msn_ftp_abort(file, "read returned EOF while reading data header from msn client"); 520 } else if (buf[0] == '\r' || buf[0] == '\n') { 521 debug("Discarding extraneous newline"); 522 } else if (buf[0] != 0) { 523 msn_ftp_abort(file, "Remote end canceled the transfer"); 493 524 /* don't really care about these last 2 (should be 0,0) */ 494 read( msn_file->fd, buf, 2);525 read(msn_file->fd, buf, 2); 495 526 return FALSE; 496 527 } else { 497 528 unsigned int size; 498 ASSERTSOCKOP( st = read( msn_file->fd, buf, 2 ), "Receiving" ); 499 if( st < 2 ) 500 return msn_ftp_abort( file, "read returned EOF while reading data header from msn client" ); 529 ASSERTSOCKOP(st = read(msn_file->fd, buf, 2), "Receiving"); 530 if (st < 2) { 531 return msn_ftp_abort(file, 532 "read returned EOF while reading data header from msn client"); 533 } 501 534 502 535 size = buf[0] + ((unsigned int) buf[1] << 8); … … 508 541 509 542 /* Text mode part of the file transfer protocol */ 510 gboolean msn_ftp_txtproto( file_transfer_t *file)543 gboolean msn_ftp_txtproto(file_transfer_t *file) 511 544 { 512 545 msn_filetransfer_t *msn_file = file->data; … … 514 547 char *tbuf = msn_file->tbuf; 515 548 516 ASSERTSOCKOP( st = read( msn_file->fd, 517 tbuf + msn_file->tbufpos, 518 sizeof( msn_file->tbuf ) - msn_file->tbufpos ), 519 "Receiving" ); 520 521 if( st == 0 ) 522 return msn_ftp_abort( file, "read returned EOF while reading text from msn client" ); 549 ASSERTSOCKOP(st = read(msn_file->fd, 550 tbuf + msn_file->tbufpos, 551 sizeof(msn_file->tbuf) - msn_file->tbufpos), 552 "Receiving"); 553 554 if (st == 0) { 555 return msn_ftp_abort(file, "read returned EOF while reading text from msn client"); 556 } 523 557 524 558 msn_file->tbufpos += st; 525 559 526 560 do { 527 for ( ;i < msn_file->tbufpos; i++) {528 if ( tbuf[i] == '\n' || tbuf[i] == '\r') {561 for (; i < msn_file->tbufpos; i++) { 562 if (tbuf[i] == '\n' || tbuf[i] == '\r') { 529 563 tbuf[i] = '\0'; 530 if( i > 0 ) 531 msn_ftp_handle_command( file, tbuf ); 532 else 533 while( tbuf[i] == '\n' || tbuf[i] == '\r' ) i++; 534 memmove( tbuf, tbuf + i + 1, msn_file->tbufpos - i - 1 ); 564 if (i > 0) { 565 msn_ftp_handle_command(file, tbuf); 566 } else { 567 while (tbuf[i] == '\n' || tbuf[i] == '\r') { 568 i++; 569 } 570 } 571 memmove(tbuf, tbuf + i + 1, msn_file->tbufpos - i - 1); 535 572 msn_file->tbufpos -= i + 1; 536 573 i = 0; … … 538 575 } 539 576 } 540 } while ( i < msn_file->tbufpos ); 541 542 if( msn_file->tbufpos == sizeof( msn_file->tbuf ) ) 543 return msn_ftp_abort( file, 544 "Line exceeded %d bytes in text protocol", 545 sizeof( msn_file->tbuf ) ); 577 } while (i < msn_file->tbufpos); 578 579 if (msn_file->tbufpos == sizeof(msn_file->tbuf)) { 580 return msn_ftp_abort(file, 581 "Line exceeded %d bytes in text protocol", 582 sizeof(msn_file->tbuf)); 583 } 546 584 return TRUE; 547 585 } 548 586 549 gboolean msn_ftp_read( gpointer data, gint fd, b_input_condition cond)587 gboolean msn_ftp_read(gpointer data, gint fd, b_input_condition cond) 550 588 { 551 589 file_transfer_t *file = data; 552 590 msn_filetransfer_t *msn_file = file->data; 553 554 if( msn_file->status & MSN_TRANSFER_RECEIVING ) 555 return msn_ftpr_read( file ); 556 else 557 return msn_ftp_txtproto( file ); 558 } 559 560 void msn_ftp_free( file_transfer_t *file ) 561 { 562 msn_filetransfer_t *msn_file = file->data; 563 564 if( msn_file->r_event_id ) 565 b_event_remove( msn_file->r_event_id ); 566 567 if( msn_file->w_event_id ) 568 b_event_remove( msn_file->w_event_id ); 569 570 if( msn_file->fd != -1 ) 571 closesocket( msn_file->fd ); 572 573 msn_file->md->filetransfers = g_slist_remove( msn_file->md->filetransfers, msn_file->dcc ); 574 575 g_free( msn_file->handle ); 576 577 g_free( msn_file ); 578 } 579 580 void msn_ftpr_accept( file_transfer_t *file ) 581 { 582 msn_filetransfer_t *msn_file = file->data; 583 584 msn_ftp_invitation_cmd( msn_file->md->ic, msn_file->handle, msn_file->invite_cookie, "ACCEPT", 585 "Launch-Application: FALSE\r\n" 586 "Request-Data: IP-Address:\r\n"); 587 } 588 589 void msn_ftp_finished( file_transfer_t *file ) 590 { 591 msn_ftp_write( file, "BYE 16777989\r\n" ); 592 } 593 594 void msn_ftp_canceled( file_transfer_t *file, char *reason ) 595 { 596 msn_filetransfer_t *msn_file = file->data; 597 598 msn_ftp_cancel_invite( msn_file->md->ic, msn_file->handle, 599 msn_file->invite_cookie, 600 file->status & FT_STATUS_TRANSFERRING ? 601 "FTTIMEOUT" : 602 "FAIL" ); 603 604 imcb_log( msn_file->md->ic, "File transfer aborted: %s", reason ); 605 } 606 607 gboolean msn_ftpr_write_request( file_transfer_t *file ) 608 { 609 msn_filetransfer_t *msn_file = file->data; 610 if( msn_file->r_event_id != 0 ) { 611 msn_ftp_abort( file, 612 "BUG in MSN file transfer:" 613 "write_request called when" 614 "already watching for input" ); 591 592 if (msn_file->status & MSN_TRANSFER_RECEIVING) { 593 return msn_ftpr_read(file); 594 } else { 595 return msn_ftp_txtproto(file); 596 } 597 } 598 599 void msn_ftp_free(file_transfer_t *file) 600 { 601 msn_filetransfer_t *msn_file = file->data; 602 603 if (msn_file->r_event_id) { 604 b_event_remove(msn_file->r_event_id); 605 } 606 607 if (msn_file->w_event_id) { 608 b_event_remove(msn_file->w_event_id); 609 } 610 611 if (msn_file->fd != -1) { 612 closesocket(msn_file->fd); 613 } 614 615 msn_file->md->filetransfers = g_slist_remove(msn_file->md->filetransfers, msn_file->dcc); 616 617 g_free(msn_file->handle); 618 619 g_free(msn_file); 620 } 621 622 void msn_ftpr_accept(file_transfer_t *file) 623 { 624 msn_filetransfer_t *msn_file = file->data; 625 626 msn_ftp_invitation_cmd(msn_file->md->ic, msn_file->handle, msn_file->invite_cookie, "ACCEPT", 627 "Launch-Application: FALSE\r\n" 628 "Request-Data: IP-Address:\r\n"); 629 } 630 631 void msn_ftp_finished(file_transfer_t *file) 632 { 633 msn_ftp_write(file, "BYE 16777989\r\n"); 634 } 635 636 void msn_ftp_canceled(file_transfer_t *file, char *reason) 637 { 638 msn_filetransfer_t *msn_file = file->data; 639 640 msn_ftp_cancel_invite(msn_file->md->ic, msn_file->handle, 641 msn_file->invite_cookie, 642 file->status & FT_STATUS_TRANSFERRING ? 643 "FTTIMEOUT" : 644 "FAIL"); 645 646 imcb_log(msn_file->md->ic, "File transfer aborted: %s", reason); 647 } 648 649 gboolean msn_ftpr_write_request(file_transfer_t *file) 650 { 651 msn_filetransfer_t *msn_file = file->data; 652 653 if (msn_file->r_event_id != 0) { 654 msn_ftp_abort(file, 655 "BUG in MSN file transfer:" 656 "write_request called when" 657 "already watching for input"); 615 658 return FALSE; 616 659 } 617 660 618 msn_file->r_event_id = 619 b_input_add( msn_file->fd, B_EV_IO_READ, msn_ftp_read, file);661 msn_file->r_event_id = 662 b_input_add(msn_file->fd, B_EV_IO_READ, msn_ftp_read, file); 620 663 621 664 return TRUE;
Note: See TracChangeset
for help on using the changeset viewer.