drv_proxy.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. /*
  2. * mbsync - mailbox synchronizer
  3. * Copyright (C) 2017 Oswald Buddenhagen <ossi@users.sf.net>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. *
  18. * As a special exception, mbsync may be linked with the OpenSSL library,
  19. * despite that library's more restrictive license.
  20. */
  21. #include "driver.h"
  22. #include <limits.h>
  23. #include <stdlib.h>
  24. typedef struct {
  25. store_t gen;
  26. const char *label; // foreign
  27. uint ref_count;
  28. driver_t *real_driver;
  29. store_t *real_store;
  30. void (*bad_callback)( void *aux );
  31. void *bad_callback_aux;
  32. } proxy_store_t;
  33. static void ATTR_PRINTFLIKE(1, 2)
  34. debug( const char *msg, ... )
  35. {
  36. va_list va;
  37. va_start( va, msg );
  38. vdebug( DEBUG_DRV, msg, va );
  39. va_end( va );
  40. }
  41. static void ATTR_PRINTFLIKE(1, 2)
  42. debugn( const char *msg, ... )
  43. {
  44. va_list va;
  45. va_start( va, msg );
  46. vdebugn( DEBUG_DRV, msg, va );
  47. va_end( va );
  48. }
  49. /* Keep the mailbox driver flag definitions in sync: */
  50. /* grep for MAILBOX_DRIVER_FLAG */
  51. /* The order is according to alphabetical maildir flag sort */
  52. static const char Flags[] = { 'D', 'F', 'P', 'R', 'S', 'T' };
  53. static char *
  54. proxy_make_flags( uchar flags, char *buf )
  55. {
  56. uint i, d;
  57. for (d = 0, i = 0; i < as(Flags); i++)
  58. if (flags & (1 << i))
  59. buf[d++] = Flags[i];
  60. buf[d] = 0;
  61. return buf;
  62. }
  63. static void
  64. proxy_store_deref( proxy_store_t *ctx )
  65. {
  66. if (!--ctx->ref_count)
  67. free( ctx );
  68. }
  69. static int curr_tag;
  70. typedef struct {
  71. uint ref_count;
  72. int tag;
  73. proxy_store_t *ctx;
  74. } gen_cmd_t;
  75. static gen_cmd_t *
  76. proxy_cmd_new( proxy_store_t *ctx, uint sz )
  77. {
  78. gen_cmd_t *cmd = nfmalloc( sz );
  79. cmd->ref_count = 2;
  80. cmd->tag = ++curr_tag;
  81. cmd->ctx = ctx;
  82. ctx->ref_count++;
  83. return cmd;
  84. }
  85. static void
  86. proxy_cmd_done( gen_cmd_t *cmd )
  87. {
  88. if (!--cmd->ref_count) {
  89. proxy_store_deref( cmd->ctx );
  90. free( cmd );
  91. }
  92. }
  93. #if 0
  94. //# TEMPLATE GETTER
  95. static @type@proxy_@name@( store_t *gctx )
  96. {
  97. proxy_store_t *ctx = (proxy_store_t *)gctx;
  98. @type@rv = ctx->real_driver->@name@( ctx->real_store );
  99. debug( "%sCalled @name@, ret=@fmt@\n", ctx->label, rv );
  100. return rv;
  101. }
  102. //# END
  103. //# TEMPLATE REGULAR
  104. static @type@proxy_@name@( store_t *gctx@decl_args@ )
  105. {
  106. proxy_store_t *ctx = (proxy_store_t *)gctx;
  107. @pre_print_args@
  108. debug( "%sEnter @name@@print_fmt_args@\n", ctx->label@print_pass_args@ );
  109. @print_args@
  110. @type@rv = ctx->real_driver->@name@( ctx->real_store@pass_args@ );
  111. debug( "%sLeave @name@, ret=@fmt@\n", ctx->label, rv );
  112. return rv;
  113. }
  114. //# END
  115. //# TEMPLATE REGULAR_VOID
  116. static void proxy_@name@( store_t *gctx@decl_args@ )
  117. {
  118. proxy_store_t *ctx = (proxy_store_t *)gctx;
  119. @pre_print_args@
  120. debug( "%sEnter @name@@print_fmt_args@\n", ctx->label@print_pass_args@ );
  121. @print_args@
  122. ctx->real_driver->@name@( ctx->real_store@pass_args@ );
  123. debug( "%sLeave @name@\n", ctx->label );
  124. @action@
  125. }
  126. //# END
  127. //# TEMPLATE CALLBACK
  128. typedef struct {
  129. gen_cmd_t gen;
  130. void (*callback)( @decl_cb_args@void *aux );
  131. void *callback_aux;
  132. @decl_state@
  133. } @name@_cmd_t;
  134. static void
  135. proxy_@name@_cb( @decl_cb_args@void *aux )
  136. {
  137. @name@_cmd_t *cmd = (@name@_cmd_t *)aux;
  138. @pre_print_cb_args@
  139. debug( "%s[% 2d] Callback enter @name@@print_fmt_cb_args@\n", cmd->gen.ctx->label, cmd->gen.tag@print_pass_cb_args@ );
  140. @print_cb_args@
  141. cmd->callback( @pass_cb_args@cmd->callback_aux );
  142. debug( "%s[% 2d] Callback leave @name@\n", cmd->gen.ctx->label, cmd->gen.tag );
  143. proxy_cmd_done( &cmd->gen );
  144. }
  145. static void
  146. proxy_@name@( store_t *gctx@decl_args@, void (*cb)( @decl_cb_args@void *aux ), void *aux )
  147. {
  148. proxy_store_t *ctx = (proxy_store_t *)gctx;
  149. @name@_cmd_t *cmd = (@name@_cmd_t *)proxy_cmd_new( ctx, sizeof(@name@_cmd_t) );
  150. cmd->callback = cb;
  151. cmd->callback_aux = aux;
  152. @assign_state@
  153. @pre_print_args@
  154. debug( "%s[% 2d] Enter @name@@print_fmt_args@\n", ctx->label, cmd->gen.tag@print_pass_args@ );
  155. @print_args@
  156. ctx->real_driver->@name@( ctx->real_store@pass_args@, proxy_@name@_cb, cmd );
  157. debug( "%s[% 2d] Leave @name@\n", ctx->label, cmd->gen.tag );
  158. proxy_cmd_done( &cmd->gen );
  159. }
  160. //# END
  161. //# UNDEFINE list_store_print_fmt_cb_args
  162. //# UNDEFINE list_store_print_pass_cb_args
  163. //# DEFINE list_store_print_cb_args
  164. if (sts == DRV_OK) {
  165. for (string_list_t *box = boxes; box; box = box->next)
  166. debug( " %s\n", box->string );
  167. }
  168. //# END
  169. //# DEFINE load_box_pre_print_args
  170. static char ubuf[12];
  171. //# END
  172. //# DEFINE load_box_print_fmt_args , [%u,%s] (find >= %u, paired <= %u, new > %u)
  173. //# DEFINE load_box_print_pass_args , minuid, (maxuid == UINT_MAX) ? "inf" : (nfsnprintf( ubuf, sizeof(ubuf), "%u", maxuid ), ubuf), finduid, pairuid, newuid
  174. //# DEFINE load_box_print_args
  175. if (excs.size) {
  176. debugn( " excs:" );
  177. for (uint t = 0; t < excs.size; t++)
  178. debugn( " %u", excs.data[t] );
  179. debug( "\n" );
  180. }
  181. //# END
  182. //# DEFINE load_box_pre_print_cb_args
  183. static char fbuf[as(Flags) + 1];
  184. //# END
  185. //# DEFINE load_box_print_fmt_cb_args , sts=%d, total=%d, recent=%d
  186. //# DEFINE load_box_print_pass_cb_args , sts, total_msgs, recent_msgs
  187. //# DEFINE load_box_print_cb_args
  188. if (sts == DRV_OK) {
  189. for (message_t *msg = msgs; msg; msg = msg->next)
  190. debug( " uid=%-5u flags=%-4s size=%-6u tuid=%." stringify(TUIDL) "s\n",
  191. msg->uid, (msg->status & M_FLAGS) ? (proxy_make_flags( msg->flags, fbuf ), fbuf) : "?", msg->size, *msg->tuid ? msg->tuid : "?" );
  192. }
  193. //# END
  194. //# DEFINE find_new_msgs_print_fmt_cb_args , sts=%d
  195. //# DEFINE find_new_msgs_print_pass_cb_args , sts
  196. //# DEFINE find_new_msgs_print_cb_args
  197. if (sts == DRV_OK) {
  198. for (message_t *msg = msgs; msg; msg = msg->next)
  199. debug( " uid=%-5u tuid=%." stringify(TUIDL) "s\n", msg->uid, msg->tuid );
  200. }
  201. //# END
  202. //# DEFINE fetch_msg_decl_state
  203. msg_data_t *data;
  204. //# END
  205. //# DEFINE fetch_msg_assign_state
  206. cmd->data = data;
  207. //# END
  208. //# DEFINE fetch_msg_print_fmt_args , uid=%u, want_flags=%s, want_date=%s
  209. //# DEFINE fetch_msg_print_pass_args , msg->uid, !(msg->status & M_FLAGS) ? "yes" : "no", data->date ? "yes" : "no"
  210. //# DEFINE fetch_msg_pre_print_cb_args
  211. static char fbuf[as(Flags) + 1];
  212. proxy_make_flags( cmd->data->flags, fbuf );
  213. //# END
  214. //# DEFINE fetch_msg_print_fmt_cb_args , flags=%s, date=%lld, size=%u
  215. //# DEFINE fetch_msg_print_pass_cb_args , fbuf, (long long)cmd->data->date, cmd->data->len
  216. //# DEFINE fetch_msg_print_cb_args
  217. if (sts == DRV_OK && (DFlags & DEBUG_DRV_ALL)) {
  218. printf( "%s=========\n", cmd->gen.ctx->label );
  219. fwrite( cmd->data->data, cmd->data->len, 1, stdout );
  220. printf( "%s=========\n", cmd->gen.ctx->label );
  221. fflush( stdout );
  222. }
  223. //# END
  224. //# DEFINE store_msg_pre_print_args
  225. static char fbuf[as(Flags) + 1];
  226. proxy_make_flags( data->flags, fbuf );
  227. //# END
  228. //# DEFINE store_msg_print_fmt_args , flags=%s, date=%lld, size=%u, to_trash=%s
  229. //# DEFINE store_msg_print_pass_args , fbuf, (long long)data->date, data->len, to_trash ? "yes" : "no"
  230. //# DEFINE store_msg_print_args
  231. if (DFlags & DEBUG_DRV_ALL) {
  232. printf( "%s>>>>>>>>>\n", ctx->label );
  233. fwrite( data->data, data->len, 1, stdout );
  234. printf( "%s>>>>>>>>>\n", ctx->label );
  235. fflush( stdout );
  236. }
  237. //# END
  238. //# DEFINE set_msg_flags_pre_print_args
  239. static char fbuf1[as(Flags) + 1], fbuf2[as(Flags) + 1];
  240. proxy_make_flags( add, fbuf1 );
  241. proxy_make_flags( del, fbuf2 );
  242. //# END
  243. //# DEFINE set_msg_flags_print_fmt_args , uid=%u, add=%s, del=%s
  244. //# DEFINE set_msg_flags_print_pass_args , uid, fbuf1, fbuf2
  245. //# DEFINE trash_msg_print_fmt_args , uid=%u
  246. //# DEFINE trash_msg_print_pass_args , msg->uid
  247. //# DEFINE free_store_action
  248. proxy_store_deref( ctx );
  249. //# END
  250. //# DEFINE cancel_store_action
  251. proxy_store_deref( ctx );
  252. //# END
  253. #endif
  254. //# SPECIAL set_bad_callback
  255. static void
  256. proxy_set_bad_callback( store_t *gctx, void (*cb)( void *aux ), void *aux )
  257. {
  258. proxy_store_t *ctx = (proxy_store_t *)gctx;
  259. ctx->bad_callback = cb;
  260. ctx->bad_callback_aux = aux;
  261. }
  262. static void
  263. proxy_invoke_bad_callback( proxy_store_t *ctx )
  264. {
  265. ctx->ref_count++;
  266. debug( "%sCallback enter bad store\n", ctx->label );
  267. ctx->bad_callback( ctx->bad_callback_aux );
  268. debug( "%sCallback leave bad store\n", ctx->label );
  269. proxy_store_deref( ctx );
  270. }
  271. //# EXCLUDE alloc_store
  272. store_t *
  273. proxy_alloc_store( store_t *real_ctx, const char *label )
  274. {
  275. proxy_store_t *ctx;
  276. ctx = nfcalloc( sizeof(*ctx) );
  277. ctx->gen.driver = &proxy_driver;
  278. ctx->gen.conf = real_ctx->conf;
  279. ctx->ref_count = 1;
  280. ctx->label = label;
  281. ctx->real_driver = real_ctx->driver;
  282. ctx->real_store = real_ctx;
  283. ctx->real_driver->set_bad_callback( ctx->real_store, (void (*)(void *))proxy_invoke_bad_callback, ctx );
  284. return &ctx->gen;
  285. }
  286. //# EXCLUDE parse_store
  287. //# EXCLUDE cleanup
  288. //# EXCLUDE get_fail_state
  289. #include "drv_proxy.inc"