src/protocols/sametime/meanwhile/srvc_ft.c

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

mercurial