|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
/*
|
|
Packit Service |
37472d |
Meanwhile - Unofficial Lotus Sametime Community Client Library
|
|
Packit Service |
37472d |
Copyright (C) 2004 Christopher (siege) O'Brien
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
This library is free software; you can redistribute it and/or
|
|
Packit Service |
37472d |
modify it under the terms of the GNU Library General Public
|
|
Packit Service |
37472d |
License as published by the Free Software Foundation; either
|
|
Packit Service |
37472d |
version 2 of the License, or (at your option) any later version.
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
This library is distributed in the hope that it will be useful,
|
|
Packit Service |
37472d |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
37472d |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit Service |
37472d |
Library General Public License for more details.
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
You should have received a copy of the GNU Library General Public
|
|
Packit Service |
37472d |
License along with this library; if not, write to the Free
|
|
Packit Service |
37472d |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
Packit Service |
37472d |
*/
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
1bfe49 |
#include <glib.h>
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
#include "mw_channel.h"
|
|
Packit Service |
37472d |
#include "mw_common.h"
|
|
Packit Service |
37472d |
#include "mw_debug.h"
|
|
Packit Service |
37472d |
#include "mw_error.h"
|
|
Packit Service |
37472d |
#include "mw_message.h"
|
|
Packit Service |
37472d |
#include "mw_service.h"
|
|
Packit Service |
37472d |
#include "mw_session.h"
|
|
Packit Service |
37472d |
#include "mw_srvc_ft.h"
|
|
Packit Service |
37472d |
#include "mw_util.h"
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
#define PROTOCOL_TYPE 0x00000000
|
|
Packit Service |
37472d |
#define PROTOCOL_VER 0x00000001
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
/** send-on-channel type: FT transfer data */
|
|
Packit Service |
37472d |
#define msg_TRANSFER 0x0001
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
/** ack received transfer data */
|
|
Packit Service |
37472d |
#define msg_RECEIVED 0x0002
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
struct mwServiceFileTransfer {
|
|
Packit Service |
37472d |
struct mwService service;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
struct mwFileTransferHandler *handler;
|
|
Packit Service |
37472d |
GList *transfers;
|
|
Packit Service |
37472d |
};
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
struct mwFileTransfer {
|
|
Packit Service |
37472d |
struct mwServiceFileTransfer *service;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
struct mwChannel *channel;
|
|
Packit Service |
37472d |
struct mwIdBlock who;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
enum mwFileTransferState state;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
char *filename;
|
|
Packit Service |
37472d |
char *message;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
guint32 size;
|
|
Packit Service |
37472d |
guint32 remaining;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
struct mw_datum client_data;
|
|
Packit Service |
37472d |
};
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
/** momentarily places a mwLoginInfo into a mwIdBlock */
|
|
Packit Service |
37472d |
static void login_into_id(struct mwIdBlock *to, struct mwLoginInfo *from) {
|
|
Packit Service |
37472d |
to->user = from->user_id;
|
|
Packit Service |
37472d |
to->community = from->community;
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
static const char *ft_state_str(enum mwFileTransferState state) {
|
|
Packit Service |
37472d |
switch(state) {
|
|
Packit Service |
37472d |
case mwFileTransfer_NEW:
|
|
Packit Service |
37472d |
return "new";
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
case mwFileTransfer_PENDING:
|
|
Packit Service |
37472d |
return "pending";
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
case mwFileTransfer_OPEN:
|
|
Packit Service |
37472d |
return "open";
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
case mwFileTransfer_CANCEL_LOCAL:
|
|
Packit Service |
37472d |
return "cancelled locally";
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
case mwFileTransfer_CANCEL_REMOTE:
|
|
Packit Service |
37472d |
return "cancelled remotely";
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
case mwFileTransfer_DONE:
|
|
Packit Service |
37472d |
return "done";
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
case mwFileTransfer_ERROR:
|
|
Packit Service |
37472d |
return "error";
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
case mwFileTransfer_UNKNOWN:
|
|
Packit Service |
37472d |
default:
|
|
Packit Service |
37472d |
return "UNKNOWN";
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
static void ft_state(struct mwFileTransfer *ft,
|
|
Packit Service |
37472d |
enum mwFileTransferState state) {
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
g_return_if_fail(ft != NULL);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
if(ft->state == state) return;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
g_info("setting ft (%s, %s) state: %s",
|
|
Packit Service |
37472d |
NSTR(ft->who.user), NSTR(ft->who.community),
|
|
Packit Service |
37472d |
ft_state_str(state));
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
ft->state = state;
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
static void recv_channelCreate(struct mwServiceFileTransfer *srvc,
|
|
Packit Service |
37472d |
struct mwChannel *chan,
|
|
Packit Service |
37472d |
struct mwMsgChannelCreate *msg) {
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
struct mwFileTransferHandler *handler;
|
|
Packit Service |
37472d |
struct mwGetBuffer *b;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
char *fnm, *txt;
|
|
Packit Service |
37472d |
guint32 size, junk;
|
|
Packit Service |
37472d |
gboolean b_err;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
g_return_if_fail(srvc->handler != NULL);
|
|
Packit Service |
37472d |
handler = srvc->handler;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
b = mwGetBuffer_wrap(&msg->addtl);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
guint32_get(b, &junk); /* unknown */
|
|
Packit Service |
37472d |
mwString_get(b, &fnm;; /* offered filename */
|
|
Packit Service |
37472d |
mwString_get(b, &txt); /* offering message */
|
|
Packit Service |
37472d |
guint32_get(b, &size); /* size of offered file */
|
|
Packit Service |
653353 |
/* guint32_get(b, &junk); */ /* unknown */
|
|
Packit Service |
37472d |
/* and we just skip an unknown guint16 at the end */
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
b_err = mwGetBuffer_error(b);
|
|
Packit Service |
37472d |
mwGetBuffer_free(b);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
if(b_err) {
|
|
Packit Service |
37472d |
g_warning("bad/malformed addtl in File Transfer service");
|
|
Packit Service |
37472d |
mwChannel_destroy(chan, ERR_FAILURE, NULL);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
} else {
|
|
Packit Service |
37472d |
struct mwIdBlock idb;
|
|
Packit Service |
37472d |
struct mwFileTransfer *ft;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
login_into_id(&idb, mwChannel_getUser(chan));
|
|
Packit Service |
37472d |
ft = mwFileTransfer_new(srvc, &idb, txt, fnm, size);
|
|
Packit Service |
37472d |
ft->channel = chan;
|
|
Packit Service |
37472d |
ft_state(ft, mwFileTransfer_PENDING);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
mwChannel_setServiceData(chan, ft, NULL);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
if(handler->ft_offered)
|
|
Packit Service |
37472d |
handler->ft_offered(ft);
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
g_free(fnm);
|
|
Packit Service |
37472d |
g_free(txt);
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
static void recv_channelAccept(struct mwServiceFileTransfer *srvc,
|
|
Packit Service |
37472d |
struct mwChannel *chan,
|
|
Packit Service |
37472d |
struct mwMsgChannelAccept *msg) {
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
struct mwFileTransferHandler *handler;
|
|
Packit Service |
37472d |
struct mwFileTransfer *ft;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
g_return_if_fail(srvc->handler != NULL);
|
|
Packit Service |
37472d |
handler = srvc->handler;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
ft = mwChannel_getServiceData(chan);
|
|
Packit Service |
37472d |
g_return_if_fail(ft != NULL);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
ft_state(ft, mwFileTransfer_OPEN);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
if(handler->ft_opened)
|
|
Packit Service |
37472d |
handler->ft_opened(ft);
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
static void recv_channelDestroy(struct mwServiceFileTransfer *srvc,
|
|
Packit Service |
37472d |
struct mwChannel *chan,
|
|
Packit Service |
37472d |
struct mwMsgChannelDestroy *msg) {
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
struct mwFileTransferHandler *handler;
|
|
Packit Service |
37472d |
struct mwFileTransfer *ft;
|
|
Packit Service |
37472d |
guint32 code;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
code = msg->reason;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
g_return_if_fail(srvc->handler != NULL);
|
|
Packit Service |
37472d |
handler = srvc->handler;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
ft = mwChannel_getServiceData(chan);
|
|
Packit Service |
37472d |
g_return_if_fail(ft != NULL);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
ft->channel = NULL;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
if(! mwFileTransfer_isDone(ft))
|
|
Packit Service |
37472d |
ft_state(ft, mwFileTransfer_CANCEL_REMOTE);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
mwFileTransfer_close(ft, code);
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
static void recv_TRANSFER(struct mwFileTransfer *ft,
|
|
Packit Service |
37472d |
struct mwOpaque *data) {
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
struct mwServiceFileTransfer *srvc;
|
|
Packit Service |
37472d |
struct mwFileTransferHandler *handler;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
srvc = ft->service;
|
|
Packit Service |
37472d |
handler = srvc->handler;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
g_return_if_fail(mwFileTransfer_isOpen(ft));
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
if(data->len > ft->remaining) {
|
|
Packit Service |
37472d |
/* @todo handle error */
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
} else {
|
|
Packit Service |
37472d |
ft->remaining -= data->len;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
if(! ft->remaining)
|
|
Packit Service |
37472d |
ft_state(ft, mwFileTransfer_DONE);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
if(handler->ft_recv)
|
|
Packit Service |
37472d |
handler->ft_recv(ft, data);
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
static void recv_RECEIVED(struct mwFileTransfer *ft,
|
|
Packit Service |
37472d |
struct mwOpaque *data) {
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
struct mwServiceFileTransfer *srvc;
|
|
Packit Service |
37472d |
struct mwFileTransferHandler *handler;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
srvc = ft->service;
|
|
Packit Service |
37472d |
handler = srvc->handler;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
if(! ft->remaining)
|
|
Packit Service |
37472d |
ft_state(ft, mwFileTransfer_DONE);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
if(handler->ft_ack)
|
|
Packit Service |
37472d |
handler->ft_ack(ft);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
if(! ft->remaining)
|
|
Packit Service |
37472d |
mwFileTransfer_close(ft, mwFileTransfer_SUCCESS);
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
static void recv(struct mwService *srvc, struct mwChannel *chan,
|
|
Packit Service |
37472d |
guint16 type, struct mwOpaque *data) {
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
struct mwFileTransfer *ft;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
ft = mwChannel_getServiceData(chan);
|
|
Packit Service |
37472d |
g_return_if_fail(ft != NULL);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
switch(type) {
|
|
Packit Service |
37472d |
case msg_TRANSFER:
|
|
Packit Service |
37472d |
recv_TRANSFER(ft, data);
|
|
Packit Service |
37472d |
break;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
case msg_RECEIVED:
|
|
Packit Service |
37472d |
recv_RECEIVED(ft, data);
|
|
Packit Service |
37472d |
break;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
default:
|
|
Packit Service |
37472d |
mw_mailme_opaque(data, "unknown message in ft service: 0x%04x", type);
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
static void clear(struct mwServiceFileTransfer *srvc) {
|
|
Packit Service |
37472d |
struct mwFileTransferHandler *h;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
h = srvc->handler;
|
|
Packit Service |
37472d |
if(h && h->clear)
|
|
Packit Service |
37472d |
h->clear(srvc);
|
|
Packit Service |
37472d |
srvc->handler = NULL;
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
static const char *name(struct mwService *srvc) {
|
|
Packit Service |
37472d |
return "File Transfer";
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
static const char *desc(struct mwService *srvc) {
|
|
Packit Service |
37472d |
return "Provides file transfer capabilities through the community server";
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
static void start(struct mwService *srvc) {
|
|
Packit Service |
37472d |
mwService_started(srvc);
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
static void stop(struct mwServiceFileTransfer *srvc) {
|
|
Packit Service |
37472d |
while(srvc->transfers) {
|
|
Packit Service |
37472d |
mwFileTransfer_free(srvc->transfers->data);
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
mwService_stopped(MW_SERVICE(srvc));
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
struct mwServiceFileTransfer *
|
|
Packit Service |
37472d |
mwServiceFileTransfer_new(struct mwSession *session,
|
|
Packit Service |
37472d |
struct mwFileTransferHandler *handler) {
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
struct mwServiceFileTransfer *srvc_ft;
|
|
Packit Service |
37472d |
struct mwService *srvc;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
g_return_val_if_fail(session != NULL, NULL);
|
|
Packit Service |
37472d |
g_return_val_if_fail(handler != NULL, NULL);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
srvc_ft = g_new0(struct mwServiceFileTransfer, 1);
|
|
Packit Service |
37472d |
srvc = MW_SERVICE(srvc_ft);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
mwService_init(srvc, session, mwService_FILE_TRANSFER);
|
|
Packit Service |
37472d |
srvc->recv_create = (mwService_funcRecvCreate) recv_channelCreate;
|
|
Packit Service |
37472d |
srvc->recv_accept = (mwService_funcRecvAccept) recv_channelAccept;
|
|
Packit Service |
37472d |
srvc->recv_destroy = (mwService_funcRecvDestroy) recv_channelDestroy;
|
|
Packit Service |
37472d |
srvc->recv = recv;
|
|
Packit Service |
37472d |
srvc->clear = (mwService_funcClear) clear;
|
|
Packit Service |
37472d |
srvc->get_name = name;
|
|
Packit Service |
37472d |
srvc->get_desc = desc;
|
|
Packit Service |
37472d |
srvc->start = start;
|
|
Packit Service |
37472d |
srvc->stop = (mwService_funcStop) stop;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
srvc_ft->handler = handler;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
return srvc_ft;
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
struct mwFileTransferHandler *
|
|
Packit Service |
37472d |
mwServiceFileTransfer_getHandler(struct mwServiceFileTransfer *srvc) {
|
|
Packit Service |
37472d |
g_return_val_if_fail(srvc != NULL, NULL);
|
|
Packit Service |
37472d |
return srvc->handler;
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
const GList *
|
|
Packit Service |
37472d |
mwServiceFileTransfer_getTransfers(struct mwServiceFileTransfer *srvc) {
|
|
Packit Service |
37472d |
g_return_val_if_fail(srvc != NULL, NULL);
|
|
Packit Service |
37472d |
return srvc->transfers;
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
struct mwFileTransfer *
|
|
Packit Service |
37472d |
mwFileTransfer_new(struct mwServiceFileTransfer *srvc,
|
|
Packit Service |
37472d |
const struct mwIdBlock *who, const char *msg,
|
|
Packit Service |
37472d |
const char *filename, guint32 filesize) {
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
struct mwFileTransfer *ft;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
g_return_val_if_fail(srvc != NULL, NULL);
|
|
Packit Service |
37472d |
g_return_val_if_fail(who != NULL, NULL);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
ft = g_new0(struct mwFileTransfer, 1);
|
|
Packit Service |
37472d |
ft->service = srvc;
|
|
Packit Service |
37472d |
mwIdBlock_clone(&ft->who, who);
|
|
Packit Service |
37472d |
ft->filename = g_strdup(filename);
|
|
Packit Service |
37472d |
ft->message = g_strdup(msg);
|
|
Packit Service |
37472d |
ft->size = ft->remaining = filesize;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
ft_state(ft, mwFileTransfer_NEW);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
/* stick a reference in the service */
|
|
Packit Service |
37472d |
srvc->transfers = g_list_prepend(srvc->transfers, ft);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
return ft;
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
struct mwServiceFileTransfer *
|
|
Packit Service |
37472d |
mwFileTransfer_getService(struct mwFileTransfer *ft) {
|
|
Packit Service |
37472d |
g_return_val_if_fail(ft != NULL, NULL);
|
|
Packit Service |
37472d |
return ft->service;
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
enum mwFileTransferState
|
|
Packit Service |
37472d |
mwFileTransfer_getState(struct mwFileTransfer *ft) {
|
|
Packit Service |
37472d |
g_return_val_if_fail(ft != NULL, mwFileTransfer_UNKNOWN);
|
|
Packit Service |
37472d |
return ft->state;
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
const struct mwIdBlock *
|
|
Packit Service |
37472d |
mwFileTransfer_getUser(struct mwFileTransfer *ft) {
|
|
Packit Service |
37472d |
g_return_val_if_fail(ft != NULL, NULL);
|
|
Packit Service |
37472d |
return &ft->who;
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
const char *
|
|
Packit Service |
37472d |
mwFileTransfer_getMessage(struct mwFileTransfer *ft) {
|
|
Packit Service |
37472d |
g_return_val_if_fail(ft != NULL, NULL);
|
|
Packit Service |
37472d |
return ft->message;
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
const char *
|
|
Packit Service |
37472d |
mwFileTransfer_getFileName(struct mwFileTransfer *ft) {
|
|
Packit Service |
37472d |
g_return_val_if_fail(ft != NULL, NULL);
|
|
Packit Service |
37472d |
return ft->filename;
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
guint32 mwFileTransfer_getFileSize(struct mwFileTransfer *ft) {
|
|
Packit Service |
37472d |
g_return_val_if_fail(ft != NULL, 0);
|
|
Packit Service |
37472d |
return ft->size;
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
guint32 mwFileTransfer_getRemaining(struct mwFileTransfer *ft) {
|
|
Packit Service |
37472d |
g_return_val_if_fail(ft != NULL, 0);
|
|
Packit Service |
37472d |
return ft->remaining;
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
int mwFileTransfer_accept(struct mwFileTransfer *ft) {
|
|
Packit Service |
37472d |
struct mwServiceFileTransfer *srvc;
|
|
Packit Service |
37472d |
struct mwFileTransferHandler *handler;
|
|
Packit Service |
37472d |
int ret;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
g_return_val_if_fail(ft != NULL, -1);
|
|
Packit Service |
37472d |
g_return_val_if_fail(ft->channel != NULL, -1);
|
|
Packit Service |
37472d |
g_return_val_if_fail(mwFileTransfer_isPending(ft), -1);
|
|
Packit Service |
37472d |
g_return_val_if_fail(mwChannel_isIncoming(ft->channel), -1);
|
|
Packit Service |
37472d |
g_return_val_if_fail(mwChannel_isState(ft->channel, mwChannel_WAIT), -1);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
g_return_val_if_fail(ft->service != NULL, -1);
|
|
Packit Service |
37472d |
srvc = ft->service;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
g_return_val_if_fail(srvc->handler != NULL, -1);
|
|
Packit Service |
37472d |
handler = srvc->handler;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
ret = mwChannel_accept(ft->channel);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
if(ret) {
|
|
Packit Service |
37472d |
mwFileTransfer_close(ft, ERR_FAILURE);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
} else {
|
|
Packit Service |
37472d |
ft_state(ft, mwFileTransfer_OPEN);
|
|
Packit Service |
37472d |
if(handler->ft_opened)
|
|
Packit Service |
37472d |
handler->ft_opened(ft);
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
return ret;
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
static void ft_create_chan(struct mwFileTransfer *ft) {
|
|
Packit Service |
37472d |
struct mwSession *s;
|
|
Packit Service |
37472d |
struct mwChannelSet *cs;
|
|
Packit Service |
37472d |
struct mwChannel *chan;
|
|
Packit Service |
37472d |
struct mwLoginInfo *login;
|
|
Packit Service |
37472d |
struct mwPutBuffer *b;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
/* we only should be calling this if there isn't a channel already
|
|
Packit Service |
37472d |
associated with the conversation */
|
|
Packit Service |
37472d |
g_return_if_fail(ft != NULL);
|
|
Packit Service |
37472d |
g_return_if_fail(mwFileTransfer_isNew(ft));
|
|
Packit Service |
37472d |
g_return_if_fail(ft->channel == NULL);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
s = mwService_getSession(MW_SERVICE(ft->service));
|
|
Packit Service |
37472d |
cs = mwSession_getChannels(s);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
chan = mwChannel_newOutgoing(cs);
|
|
Packit Service |
37472d |
mwChannel_setService(chan, MW_SERVICE(ft->service));
|
|
Packit Service |
37472d |
mwChannel_setProtoType(chan, PROTOCOL_TYPE);
|
|
Packit Service |
37472d |
mwChannel_setProtoVer(chan, PROTOCOL_VER);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
/* offer all known ciphers */
|
|
Packit Service |
37472d |
mwChannel_populateSupportedCipherInstances(chan);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
/* set the target */
|
|
Packit Service |
37472d |
login = mwChannel_getUser(chan);
|
|
Packit Service |
37472d |
login->user_id = g_strdup(ft->who.user);
|
|
Packit Service |
37472d |
login->community = g_strdup(ft->who.community);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
/* compose the addtl create */
|
|
Packit Service |
37472d |
b = mwPutBuffer_new();
|
|
Packit Service |
37472d |
guint32_put(b, 0x00);
|
|
Packit Service |
37472d |
mwString_put(b, ft->filename);
|
|
Packit Service |
37472d |
mwString_put(b, ft->message);
|
|
Packit Service |
37472d |
guint32_put(b, ft->size);
|
|
Packit Service |
37472d |
guint32_put(b, 0x00);
|
|
Packit Service |
37472d |
guint16_put(b, 0x00);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
mwPutBuffer_finalize(mwChannel_getAddtlCreate(chan), b);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
ft->channel = mwChannel_create(chan)? NULL: chan;
|
|
Packit Service |
37472d |
if(ft->channel) {
|
|
Packit Service |
37472d |
mwChannel_setServiceData(ft->channel, ft, NULL);
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
int mwFileTransfer_offer(struct mwFileTransfer *ft) {
|
|
Packit Service |
37472d |
struct mwServiceFileTransfer *srvc;
|
|
Packit Service |
37472d |
struct mwFileTransferHandler *handler;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
g_return_val_if_fail(ft != NULL, -1);
|
|
Packit Service |
37472d |
g_return_val_if_fail(ft->channel == NULL, -1);
|
|
Packit Service |
37472d |
g_return_val_if_fail(mwFileTransfer_isNew(ft), -1);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
g_return_val_if_fail(ft->service != NULL, -1);
|
|
Packit Service |
37472d |
srvc = ft->service;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
g_return_val_if_fail(srvc->handler != NULL, -1);
|
|
Packit Service |
37472d |
handler = srvc->handler;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
ft_create_chan(ft);
|
|
Packit Service |
37472d |
if(ft->channel) {
|
|
Packit Service |
37472d |
ft_state(ft, mwFileTransfer_PENDING);
|
|
Packit Service |
37472d |
} else {
|
|
Packit Service |
37472d |
ft_state(ft, mwFileTransfer_ERROR);
|
|
Packit Service |
37472d |
mwFileTransfer_close(ft, ERR_FAILURE);
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
return 0;
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
int mwFileTransfer_close(struct mwFileTransfer *ft, guint32 code) {
|
|
Packit Service |
37472d |
struct mwServiceFileTransfer *srvc;
|
|
Packit Service |
37472d |
struct mwFileTransferHandler *handler;
|
|
Packit Service |
37472d |
int ret = 0;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
g_return_val_if_fail(ft != NULL, -1);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
if(mwFileTransfer_isOpen(ft))
|
|
Packit Service |
37472d |
ft_state(ft, mwFileTransfer_CANCEL_LOCAL);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
if(ft->channel) {
|
|
Packit Service |
37472d |
ret = mwChannel_destroy(ft->channel, code, NULL);
|
|
Packit Service |
37472d |
ft->channel = NULL;
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
srvc = ft->service;
|
|
Packit Service |
37472d |
g_return_val_if_fail(srvc != NULL, ret);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
handler = srvc->handler;
|
|
Packit Service |
37472d |
g_return_val_if_fail(handler != NULL, ret);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
if(handler->ft_closed)
|
|
Packit Service |
37472d |
handler->ft_closed(ft, code);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
return ret;
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
void mwFileTransfer_free(struct mwFileTransfer *ft) {
|
|
Packit Service |
37472d |
struct mwServiceFileTransfer *srvc;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
if(! ft) return;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
srvc = ft->service;
|
|
Packit Service |
37472d |
if(srvc)
|
|
Packit Service |
37472d |
srvc->transfers = g_list_remove(srvc->transfers, ft);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
if(ft->channel) {
|
|
Packit Service |
37472d |
mwChannel_destroy(ft->channel, mwFileTransfer_SUCCESS, NULL);
|
|
Packit Service |
37472d |
ft->channel = NULL;
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
mwFileTransfer_removeClientData(ft);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
mwIdBlock_clear(&ft->who);
|
|
Packit Service |
37472d |
g_free(ft->filename);
|
|
Packit Service |
37472d |
g_free(ft->message);
|
|
Packit Service |
37472d |
g_free(ft);
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
int mwFileTransfer_send(struct mwFileTransfer *ft,
|
|
Packit Service |
37472d |
struct mwOpaque *data) {
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
struct mwChannel *chan;
|
|
Packit Service |
37472d |
int ret;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
g_return_val_if_fail(ft != NULL, -1);
|
|
Packit Service |
37472d |
g_return_val_if_fail(mwFileTransfer_isOpen(ft), -1);
|
|
Packit Service |
37472d |
g_return_val_if_fail(ft->channel != NULL, -1);
|
|
Packit Service |
37472d |
chan = ft->channel;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
g_return_val_if_fail(mwChannel_isOutgoing(chan), -1);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
if(data->len > ft->remaining) {
|
|
Packit Service |
37472d |
/* @todo handle error */
|
|
Packit Service |
37472d |
return -1;
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
ret = mwChannel_send(chan, msg_TRANSFER, data);
|
|
Packit Service |
37472d |
if(! ret) ft->remaining -= data->len;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
/* we're not done until we receive an ACK for the last piece of
|
|
Packit Service |
37472d |
outgoing data */
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
return ret;
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
int mwFileTransfer_ack(struct mwFileTransfer *ft) {
|
|
Packit Service |
37472d |
struct mwChannel *chan;
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
g_return_val_if_fail(ft != NULL, -1);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
chan = ft->channel;
|
|
Packit Service |
37472d |
g_return_val_if_fail(chan != NULL, -1);
|
|
Packit Service |
37472d |
g_return_val_if_fail(mwChannel_isIncoming(chan), -1);
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
return mwChannel_sendEncrypted(chan, msg_RECEIVED, NULL, FALSE);
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
void mwFileTransfer_setClientData(struct mwFileTransfer *ft,
|
|
Packit Service |
37472d |
gpointer data, GDestroyNotify clean) {
|
|
Packit Service |
37472d |
g_return_if_fail(ft != NULL);
|
|
Packit Service |
37472d |
mw_datum_set(&ft->client_data, data, clean);
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
gpointer mwFileTransfer_getClientData(struct mwFileTransfer *ft) {
|
|
Packit Service |
37472d |
g_return_val_if_fail(ft != NULL, NULL);
|
|
Packit Service |
37472d |
return mw_datum_get(&ft->client_data);
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
|
|
Packit Service |
37472d |
void mwFileTransfer_removeClientData(struct mwFileTransfer *ft) {
|
|
Packit Service |
37472d |
g_return_if_fail(ft != NULL);
|
|
Packit Service |
37472d |
mw_datum_clear(&ft->client_data);
|
|
Packit Service |
37472d |
}
|
|
Packit Service |
37472d |
|