diff src/protocols/sametime/meanwhile/srvc_im.c @ 11943:0110fc7c6a8a

[gaim-migrate @ 14234] Bringing things up to date with the last Meanwhile release, 0.5.0 and the last gaim-meanwhile plugin release, 1.2.5 (which should be the last plugin release against oldstatus, if all goes well with HEAD and no major bugs crop up) It builds, so that's a start. The status bits that have been empty since the first import of the sametime stuff are still empty, but I'm going to try and fill those in tomorrow. I've decided to try and start using HEAD actively, to encourage me to get this freaking prpl fully functional. committer: Tailor Script <tailor@pidgin.im>
author Christopher O'Brien <siege@pidgin.im>
date Wed, 02 Nov 2005 03:39:03 +0000
parents 3ef77720e577
children d6417efb990c
line wrap: on
line diff
--- a/src/protocols/sametime/meanwhile/srvc_im.c	Wed Nov 02 03:31:38 2005 +0000
+++ b/src/protocols/sametime/meanwhile/srvc_im.c	Wed Nov 02 03:39:03 2005 +0000
@@ -50,6 +50,9 @@
 #define msg_MESSAGE  0x0064  /**< IM message */
 
 
+#define BREAKUP  2048
+
+
 /* which type of im? */
 enum mwImType {
   mwIm_TEXT  = 0x00000001,  /**< text message */
@@ -88,6 +91,8 @@
   struct mwChannel *channel;    /**< channel */
   struct mwIdBlock target;      /**< conversation target */
 
+  gboolean ext_id;              /**< special treatment, external ID */
+
   /** state of the conversation, based loosely on the state of its
       underlying channel */
   enum mwConversationState state;
@@ -178,6 +183,9 @@
     c->state = mwConversation_CLOSED;
     c->features = srvc->features;
 
+    /* mark external users */
+    c->ext_id = g_str_has_prefix(to->user, "@E ");
+
     srvc->convs = g_list_prepend(srvc->convs, c);
   }
 
@@ -258,7 +266,7 @@
   mwConversation_removeClientData(conv);
 
   srvc = conv->service;
-  srvc->convs = g_list_remove(srvc->convs, conv);
+  srvc->convs = g_list_remove_all(srvc->convs, conv);
 
   mwIdBlock_clear(&conv->target);
   g_free(conv);
@@ -316,7 +324,7 @@
   y = mwChannel_getProtoType(chan);
   z = mwChannel_getProtoVer(chan);
 
-  if( (x != SERVICE_IM) || (y != PROTOCOL_TYPE) || (z != PROTOCOL_VER) ) {
+  if( (x != mwService_IM) || (y != PROTOCOL_TYPE) || (z != PROTOCOL_VER) ) {
     g_warning("unacceptable service, proto, ver:"
 	      " 0x%08x, 0x%08x, 0x%08x", x, y, z);
     mwChannel_destroy(chan, ERR_SERVICE_NO_SUPPORT, NULL);
@@ -432,7 +440,8 @@
        messages. Fail-over to a non-html format on a new channel for
        the convo */
     if(c->features != mwImClient_PLAIN
-       && msg->reason == ERR_IM_NOT_REGISTERED) {
+       && (msg->reason == ERR_IM_NOT_REGISTERED ||
+	   msg->reason == ERR_SERVICE_NO_SUPPORT)) {
 
       g_debug("falling back on a plaintext conversation");
       c->features = mwImClient_PLAIN;
@@ -611,8 +620,8 @@
 
   default:
     
-    mw_debug_mailme(&o, "unknown data message type in IM service:"
-		    " (0x%08x, 0x%08x)", type, subtype);
+    mw_mailme_opaque(&o, "unknown data message type in IM service:"
+		     " (0x%08x, 0x%08x)", type, subtype);
   }
 
   mwOpaque_clear(&o);
@@ -708,9 +717,9 @@
   g_return_val_if_fail(hndl != NULL, NULL);
 
   srvc_im = g_new0(struct mwServiceIm, 1);
-  srvc = &srvc_im->service;
+  srvc = MW_SERVICE(srvc_im);
 
-  mwService_init(srvc, session, SERVICE_IM);
+  mwService_init(srvc, session, mwService_IM);
   srvc->recv_create = recv_channelCreate;
   srvc->recv_accept = recv_channelAccept;
   srvc->recv_destroy = recv_channelDestroy;
@@ -769,6 +778,85 @@
 }
 
 
+static int convo_send_data(struct mwConversation *conv,
+			   guint32 type, guint32 subtype,
+			   struct mwOpaque *data) {
+  struct mwPutBuffer *b;
+  struct mwOpaque o;
+  struct mwChannel *chan;
+  int ret;
+
+  chan = conv->channel;
+  g_return_val_if_fail(chan != NULL, -1);
+
+  b = mwPutBuffer_new();
+
+  guint32_put(b, mwIm_DATA);
+  guint32_put(b, type);
+  guint32_put(b, subtype);
+  mwOpaque_put(b, data);
+
+  mwPutBuffer_finalize(&o, b);
+
+  ret = mwChannel_sendEncrypted(chan, msg_MESSAGE, &o, !conv->ext_id);
+  mwOpaque_clear(&o);
+
+  return ret;
+}
+
+
+static int convo_send_multi_start(struct mwConversation *conv) {
+  return convo_send_data(conv, mwImData_MULTI_START, 0x00, NULL);
+}
+
+
+static int convo_send_multi_stop(struct mwConversation *conv) {
+  return convo_send_data(conv, mwImData_MULTI_STOP, 0x00, NULL);
+}
+
+
+/* breaks up a large message into segments, sends a start_segment
+   message, then sends each segment in turn, then sends a stop_segment
+   message */
+static int
+convo_sendSegmented(struct mwConversation *conv, const char *message,
+		    int (*send)(struct mwConversation *conv,
+				const char *msg)) {
+  char *buf = (char *) message;
+  gsize len;
+  int ret = 0;
+
+  len = strlen(buf);
+  ret = convo_send_multi_start(conv);
+
+  while(len && !ret) {
+    char tail;
+    gsize seg;
+
+    seg = BREAKUP;
+    if(len < BREAKUP)
+      seg = len;
+
+    /* temporarily NUL-terminate this segment */
+    tail = buf[seg];
+    buf[seg] = 0x00;
+
+    ret = send(conv, buf);
+
+    /* restore this segment */
+    buf[seg] = tail;
+    
+    buf += seg;
+    len -= seg;
+  }
+
+  if(! ret)
+    ret = convo_send_multi_stop(conv);
+
+  return ret;
+}
+
+
 static int convo_sendText(struct mwConversation *conv, const char *text) {
   struct mwPutBuffer *b;
   struct mwOpaque o;
@@ -780,58 +868,7 @@
   mwString_put(b, text);
 
   mwPutBuffer_finalize(&o, b);
-  ret = mwChannel_send(conv->channel, msg_MESSAGE, &o);
-  mwOpaque_clear(&o);
-
-  return ret;
-}
-
-
-static int convo_sendHtml(struct mwConversation *conv, const char *html) {
-  struct mwPutBuffer *b;
-  struct mwOpaque o;
-  int ret;
-  
-  b = mwPutBuffer_new();
-
-  guint32_put(b, mwIm_DATA);
-  guint32_put(b, mwImData_HTML);
-  guint32_put(b, 0x00);
-
-  /* use o first as a shell of an opaque for the text */
-  o.len = strlen(html);
-  o.data = (char *) html;
-  mwOpaque_put(b, &o);
-
-  /* use o again as the holder of the buffer's finalized data */
-  mwPutBuffer_finalize(&o, b);
-  ret = mwChannel_send(conv->channel, msg_MESSAGE, &o);
-  mwOpaque_clear(&o);
-
-  return ret;
-}
-
-
-static int convo_sendSubject(struct mwConversation *conv,
-			     const char *subject) {
-  struct mwPutBuffer *b;
-  struct mwOpaque o;
-  int ret;
-
-  b = mwPutBuffer_new();
-
-  guint32_put(b, mwIm_DATA);
-  guint32_put(b, mwImData_SUBJECT);
-  guint32_put(b, 0x00);
-
-  /* use o first as a shell of an opaque for the text */
-  o.len = strlen(subject);
-  o.data = (char *) subject;
-  mwOpaque_put(b, &o);
-
-  /* use o again as the holder of the buffer's finalized data */
-  mwPutBuffer_finalize(&o, b);
-  ret = mwChannel_send(conv->channel, msg_MESSAGE, &o);
+  ret = mwChannel_sendEncrypted(conv->channel, msg_MESSAGE, &o, !conv->ext_id);
   mwOpaque_clear(&o);
 
   return ret;
@@ -839,49 +876,46 @@
 
 
 static int convo_sendTyping(struct mwConversation *conv, gboolean typing) {
-  struct mwPutBuffer *b;
-  struct mwOpaque o = { 0, NULL };
-  int ret;
+  return convo_send_data(conv, mwImData_TYPING, !typing, NULL);
+}
 
-  b = mwPutBuffer_new();
-
-  guint32_put(b, mwIm_DATA);
-  guint32_put(b, mwImData_TYPING);
-  guint32_put(b, !typing);
 
-  /* not to be confusing, but we're re-using o first as an empty
-     opaque, and later as the contents of the finalized buffer */
-  mwOpaque_put(b, &o);
+static int convo_sendSubject(struct mwConversation *conv,
+			     const char *subject) {
+  struct mwOpaque o;
 
-  mwPutBuffer_finalize(&o, b);
-  ret = mwChannel_send(conv->channel, msg_MESSAGE, &o);
-  mwOpaque_clear(&o);
+  o.len = strlen(subject);
+  o.data = (char *) subject;
 
-  return ret;
+  return convo_send_data(conv, mwImData_SUBJECT, 0x00, &o);
 }
 
 
-static int convo_sendMime(struct mwConversation *conv,
-			  const char *mime) {
-  struct mwPutBuffer *b;
+static int convo_sendHtml(struct mwConversation *conv, const char *html) {
   struct mwOpaque o;
-  int ret;
+
+  o.len = strlen(html);
+  o.data = (char *) html;
 
-  b = mwPutBuffer_new();
+  if(o.len > BREAKUP) {
+    return convo_sendSegmented(conv, html, convo_sendHtml);
+  } else {
+    return convo_send_data(conv, mwImData_HTML, 0x00, &o);
+  }
+}
 
-  guint32_put(b, mwIm_DATA);
-  guint32_put(b, mwImData_MIME);
-  guint32_put(b, 0x00);
+
+static int convo_sendMime(struct mwConversation *conv, const char *mime) {
+  struct mwOpaque o;
 
   o.len = strlen(mime);
   o.data = (char *) mime;
-  mwOpaque_put(b, &o);
 
-  mwPutBuffer_finalize(&o, b);
-  ret = mwChannel_send(conv->channel, msg_MESSAGE, &o);
-  mwOpaque_clear(&o);
-
-  return ret;
+  if(o.len > BREAKUP) {
+    return convo_sendSegmented(conv, mime, convo_sendMime);
+  } else {
+    return convo_send_data(conv, mwImData_MIME, 0x00, &o);
+  }
 }