gobex.c 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. *
  4. * OBEX library with GLib integration
  5. *
  6. * Copyright (C) 2011 Intel Corporation. All rights reserved.
  7. *
  8. */
  9. #ifdef HAVE_CONFIG_H
  10. #include <config.h>
  11. #endif
  12. #include <unistd.h>
  13. #include <string.h>
  14. #include <errno.h>
  15. #include "gobex.h"
  16. #include "gobex-debug.h"
  17. #define G_OBEX_DEFAULT_MTU 4096
  18. #define G_OBEX_MINIMUM_MTU 255
  19. #define G_OBEX_MAXIMUM_MTU 65535
  20. #define G_OBEX_DEFAULT_TIMEOUT 10
  21. #define G_OBEX_ABORT_TIMEOUT 5
  22. #define G_OBEX_OP_NONE 0xff
  23. #define FINAL_BIT 0x80
  24. #define CONNID_INVALID 0xffffffff
  25. /* Challenge request */
  26. #define NONCE_TAG 0x00
  27. #define NONCE_LEN 16
  28. /* Challenge response */
  29. #define DIGEST_TAG 0x00
  30. guint gobex_debug = 0;
  31. struct srm_config {
  32. guint8 op;
  33. gboolean enabled;
  34. guint8 srm;
  35. guint8 srmp;
  36. gboolean outgoing;
  37. };
  38. struct _GObex {
  39. int ref_count;
  40. GIOChannel *io;
  41. guint io_source;
  42. gboolean (*read) (GObex *obex, GError **err);
  43. gboolean (*write) (GObex *obex, GError **err);
  44. guint8 *rx_buf;
  45. size_t rx_data;
  46. guint16 rx_pkt_len;
  47. guint8 rx_last_op;
  48. guint8 *tx_buf;
  49. size_t tx_data;
  50. size_t tx_sent;
  51. gboolean suspended;
  52. gboolean use_srm;
  53. struct srm_config *srm;
  54. guint write_source;
  55. gssize io_rx_mtu;
  56. gssize io_tx_mtu;
  57. guint16 rx_mtu;
  58. guint16 tx_mtu;
  59. guint32 conn_id;
  60. GObexApparam *authchal;
  61. GQueue *tx_queue;
  62. GSList *req_handlers;
  63. GObexFunc disconn_func;
  64. gpointer disconn_func_data;
  65. struct pending_pkt *pending_req;
  66. };
  67. struct pending_pkt {
  68. guint id;
  69. GObex *obex;
  70. GObexPacket *pkt;
  71. guint timeout;
  72. guint timeout_id;
  73. GObexResponseFunc rsp_func;
  74. gpointer rsp_data;
  75. gboolean cancelled;
  76. gboolean suspended;
  77. gboolean authenticating;
  78. };
  79. struct req_handler {
  80. guint id;
  81. guint8 opcode;
  82. GObexRequestFunc func;
  83. gpointer user_data;
  84. };
  85. struct connect_data {
  86. guint8 version;
  87. guint8 flags;
  88. guint16 mtu;
  89. } __attribute__ ((packed));
  90. struct setpath_data {
  91. guint8 flags;
  92. guint8 constants;
  93. } __attribute__ ((packed));
  94. static struct error_code {
  95. guint8 code;
  96. const char *name;
  97. } obex_errors[] = {
  98. { G_OBEX_RSP_CONTINUE, "Continue" },
  99. { G_OBEX_RSP_SUCCESS, "Success" },
  100. { G_OBEX_RSP_CREATED, "Created" },
  101. { G_OBEX_RSP_ACCEPTED, "Accepted" },
  102. { G_OBEX_RSP_NON_AUTHORITATIVE, "Non Authoritative" },
  103. { G_OBEX_RSP_NO_CONTENT, "No Content" },
  104. { G_OBEX_RSP_RESET_CONTENT, "Reset Content" },
  105. { G_OBEX_RSP_PARTIAL_CONTENT, "Partial Content" },
  106. { G_OBEX_RSP_MULTIPLE_CHOICES, "Multiple Choices" },
  107. { G_OBEX_RSP_MOVED_PERMANENTLY, "Moved Permanently" },
  108. { G_OBEX_RSP_MOVED_TEMPORARILY, "Moved Temporarily" },
  109. { G_OBEX_RSP_SEE_OTHER, "See Other" },
  110. { G_OBEX_RSP_NOT_MODIFIED, "Not Modified" },
  111. { G_OBEX_RSP_USE_PROXY, "Use Proxy" },
  112. { G_OBEX_RSP_BAD_REQUEST, "Bad Request" },
  113. { G_OBEX_RSP_UNAUTHORIZED, "Unauthorized" },
  114. { G_OBEX_RSP_PAYMENT_REQUIRED, "Payment Required" },
  115. { G_OBEX_RSP_FORBIDDEN, "Forbidden" },
  116. { G_OBEX_RSP_NOT_FOUND, "Not Found" },
  117. { G_OBEX_RSP_METHOD_NOT_ALLOWED, "Method Not Allowed" },
  118. { G_OBEX_RSP_NOT_ACCEPTABLE, "Not Acceptable" },
  119. { G_OBEX_RSP_PROXY_AUTH_REQUIRED, "Proxy Authentication Required" },
  120. { G_OBEX_RSP_REQUEST_TIME_OUT, "Request Time Out" },
  121. { G_OBEX_RSP_CONFLICT, "Conflict" },
  122. { G_OBEX_RSP_GONE, "Gone" },
  123. { G_OBEX_RSP_LENGTH_REQUIRED, "Length Required" },
  124. { G_OBEX_RSP_PRECONDITION_FAILED, "Precondition Failed" },
  125. { G_OBEX_RSP_REQ_ENTITY_TOO_LARGE, "Request Entity Too Large" },
  126. { G_OBEX_RSP_REQ_URL_TOO_LARGE, "Request URL Too Large" },
  127. { G_OBEX_RSP_UNSUPPORTED_MEDIA_TYPE, "Unsupported Media Type" },
  128. { G_OBEX_RSP_INTERNAL_SERVER_ERROR, "Internal Server Error" },
  129. { G_OBEX_RSP_NOT_IMPLEMENTED, "Not Implemented" },
  130. { G_OBEX_RSP_BAD_GATEWAY, "Bad Gateway" },
  131. { G_OBEX_RSP_SERVICE_UNAVAILABLE, "Service Unavailable" },
  132. { G_OBEX_RSP_GATEWAY_TIMEOUT, "Gateway Timeout" },
  133. { G_OBEX_RSP_VERSION_NOT_SUPPORTED, "Version Not Supported" },
  134. { G_OBEX_RSP_DATABASE_FULL, "Database Full" },
  135. { G_OBEX_RSP_DATABASE_LOCKED, "Database Locked" },
  136. { 0x00, NULL }
  137. };
  138. const char *g_obex_strerror(guint8 err_code)
  139. {
  140. struct error_code *error;
  141. for (error = obex_errors; error->name != NULL; error++) {
  142. if (error->code == err_code)
  143. return error->name;
  144. }
  145. return "<unknown>";
  146. }
  147. static ssize_t req_header_offset(guint8 opcode)
  148. {
  149. switch (opcode) {
  150. case G_OBEX_OP_CONNECT:
  151. return sizeof(struct connect_data);
  152. case G_OBEX_OP_SETPATH:
  153. return sizeof(struct setpath_data);
  154. case G_OBEX_OP_DISCONNECT:
  155. case G_OBEX_OP_PUT:
  156. case G_OBEX_OP_GET:
  157. case G_OBEX_OP_SESSION:
  158. case G_OBEX_OP_ABORT:
  159. case G_OBEX_OP_ACTION:
  160. return 0;
  161. default:
  162. return -1;
  163. }
  164. }
  165. static ssize_t rsp_header_offset(guint8 opcode)
  166. {
  167. switch (opcode) {
  168. case G_OBEX_OP_CONNECT:
  169. return sizeof(struct connect_data);
  170. case G_OBEX_OP_SETPATH:
  171. case G_OBEX_OP_DISCONNECT:
  172. case G_OBEX_OP_PUT:
  173. case G_OBEX_OP_GET:
  174. case G_OBEX_OP_SESSION:
  175. case G_OBEX_OP_ABORT:
  176. case G_OBEX_OP_ACTION:
  177. return 0;
  178. default:
  179. return -1;
  180. }
  181. }
  182. static void pending_pkt_free(struct pending_pkt *p)
  183. {
  184. if (p->obex != NULL)
  185. g_obex_unref(p->obex);
  186. if (p->timeout_id > 0)
  187. g_source_remove(p->timeout_id);
  188. g_obex_packet_free(p->pkt);
  189. g_free(p);
  190. }
  191. static gboolean req_timeout(gpointer user_data)
  192. {
  193. GObex *obex = user_data;
  194. struct pending_pkt *p = obex->pending_req;
  195. GError *err;
  196. g_assert(p != NULL);
  197. p->timeout_id = 0;
  198. obex->pending_req = NULL;
  199. err = g_error_new(G_OBEX_ERROR, G_OBEX_ERROR_TIMEOUT,
  200. "Timed out waiting for response");
  201. g_obex_debug(G_OBEX_DEBUG_ERROR, "%s", err->message);
  202. if (p->rsp_func)
  203. p->rsp_func(obex, err, NULL, p->rsp_data);
  204. g_error_free(err);
  205. pending_pkt_free(p);
  206. return FALSE;
  207. }
  208. static gboolean write_stream(GObex *obex, GError **err)
  209. {
  210. GIOStatus status;
  211. gsize bytes_written;
  212. char *buf;
  213. buf = (char *) &obex->tx_buf[obex->tx_sent];
  214. status = g_io_channel_write_chars(obex->io, buf, obex->tx_data,
  215. &bytes_written, err);
  216. if (status != G_IO_STATUS_NORMAL)
  217. return FALSE;
  218. g_obex_dump(G_OBEX_DEBUG_DATA, "<", buf, bytes_written);
  219. obex->tx_sent += bytes_written;
  220. obex->tx_data -= bytes_written;
  221. return TRUE;
  222. }
  223. static gboolean write_packet(GObex *obex, GError **err)
  224. {
  225. GIOStatus status;
  226. gsize bytes_written;
  227. char *buf;
  228. buf = (char *) &obex->tx_buf[obex->tx_sent];
  229. status = g_io_channel_write_chars(obex->io, buf, obex->tx_data,
  230. &bytes_written, err);
  231. if (status != G_IO_STATUS_NORMAL)
  232. return FALSE;
  233. if (bytes_written != obex->tx_data)
  234. return FALSE;
  235. g_obex_dump(G_OBEX_DEBUG_DATA, "<", buf, bytes_written);
  236. obex->tx_sent += bytes_written;
  237. obex->tx_data -= bytes_written;
  238. return TRUE;
  239. }
  240. static void set_srmp(GObex *obex, guint8 srmp, gboolean outgoing)
  241. {
  242. struct srm_config *config = obex->srm;
  243. if (config == NULL)
  244. return;
  245. /* Dont't reset if direction doesn't match */
  246. if (srmp > G_OBEX_SRMP_NEXT_WAIT && config->outgoing != outgoing)
  247. return;
  248. config->srmp = srmp;
  249. config->outgoing = outgoing;
  250. }
  251. static void set_srm(GObex *obex, guint8 op, guint8 srm)
  252. {
  253. struct srm_config *config = obex->srm;
  254. gboolean enable;
  255. if (config == NULL) {
  256. if (srm == G_OBEX_SRM_DISABLE)
  257. return;
  258. config = g_new0(struct srm_config, 1);
  259. config->op = op;
  260. config->srm = srm;
  261. obex->srm = config;
  262. return;
  263. }
  264. /* Indicate response, treat it as request */
  265. if (config->srm == G_OBEX_SRM_INDICATE) {
  266. if (srm != G_OBEX_SRM_ENABLE)
  267. goto done;
  268. config->srm = srm;
  269. return;
  270. }
  271. enable = (srm == G_OBEX_SRM_ENABLE);
  272. if (config->enabled == enable)
  273. goto done;
  274. config->enabled = enable;
  275. g_obex_debug(G_OBEX_DEBUG_COMMAND, "SRM %s", config->enabled ?
  276. "Enabled" : "Disabled");
  277. done:
  278. if (config->enabled)
  279. return;
  280. g_free(obex->srm);
  281. obex->srm = NULL;
  282. }
  283. static gboolean g_obex_srm_enabled(GObex *obex)
  284. {
  285. if (!obex->use_srm)
  286. return FALSE;
  287. if (obex->srm == NULL)
  288. return FALSE;
  289. return obex->srm->enabled;
  290. }
  291. static void check_srm_final(GObex *obex, guint8 op)
  292. {
  293. if (!g_obex_srm_enabled(obex))
  294. return;
  295. switch (obex->srm->op) {
  296. case G_OBEX_OP_CONNECT:
  297. return;
  298. default:
  299. if (op <= G_OBEX_RSP_CONTINUE)
  300. return;
  301. }
  302. set_srm(obex, op, G_OBEX_SRM_DISABLE);
  303. }
  304. static void setup_srm(GObex *obex, GObexPacket *pkt, gboolean outgoing)
  305. {
  306. GObexHeader *hdr;
  307. guint8 op;
  308. gboolean final;
  309. if (!obex->use_srm)
  310. return;
  311. op = g_obex_packet_get_operation(pkt, &final);
  312. hdr = g_obex_packet_get_header(pkt, G_OBEX_HDR_SRM);
  313. if (hdr != NULL) {
  314. guint8 srm;
  315. g_obex_header_get_uint8(hdr, &srm);
  316. g_obex_debug(G_OBEX_DEBUG_COMMAND, "srm 0x%02x", srm);
  317. set_srm(obex, op, srm);
  318. } else if (!g_obex_srm_enabled(obex))
  319. set_srm(obex, op, G_OBEX_SRM_DISABLE);
  320. hdr = g_obex_packet_get_header(pkt, G_OBEX_HDR_SRMP);
  321. if (hdr != NULL) {
  322. guint8 srmp;
  323. g_obex_header_get_uint8(hdr, &srmp);
  324. g_obex_debug(G_OBEX_DEBUG_COMMAND, "srmp 0x%02x", srmp);
  325. set_srmp(obex, srmp, outgoing);
  326. } else if (obex->pending_req && obex->pending_req->suspended)
  327. g_obex_packet_add_uint8(pkt, G_OBEX_HDR_SRMP, G_OBEX_SRMP_WAIT);
  328. else
  329. set_srmp(obex, -1, outgoing);
  330. if (final)
  331. check_srm_final(obex, op);
  332. }
  333. static gboolean write_data(GIOChannel *io, GIOCondition cond,
  334. gpointer user_data)
  335. {
  336. GObex *obex = user_data;
  337. if (cond & G_IO_NVAL)
  338. return FALSE;
  339. if (cond & (G_IO_HUP | G_IO_ERR))
  340. goto stop_tx;
  341. if (obex->tx_data == 0) {
  342. struct pending_pkt *p = g_queue_pop_head(obex->tx_queue);
  343. ssize_t len;
  344. if (p == NULL)
  345. goto stop_tx;
  346. setup_srm(obex, p->pkt, TRUE);
  347. if (g_obex_srm_enabled(obex))
  348. goto encode;
  349. /* Can't send a request while there's a pending one */
  350. if (obex->pending_req && p->id > 0) {
  351. g_queue_push_head(obex->tx_queue, p);
  352. goto stop_tx;
  353. }
  354. encode:
  355. len = g_obex_packet_encode(p->pkt, obex->tx_buf, obex->tx_mtu);
  356. if (len == -EAGAIN) {
  357. g_queue_push_head(obex->tx_queue, p);
  358. g_obex_suspend(obex);
  359. goto stop_tx;
  360. }
  361. if (len < 0) {
  362. pending_pkt_free(p);
  363. goto done;
  364. }
  365. if (p->id > 0) {
  366. if (obex->pending_req != NULL)
  367. pending_pkt_free(obex->pending_req);
  368. obex->pending_req = p;
  369. p->timeout_id = g_timeout_add_seconds(p->timeout,
  370. req_timeout, obex);
  371. } else {
  372. /* During packet encode final bit can be set */
  373. if (obex->tx_buf[0] & FINAL_BIT)
  374. check_srm_final(obex,
  375. obex->tx_buf[0] & ~FINAL_BIT);
  376. pending_pkt_free(p);
  377. }
  378. obex->tx_data = len;
  379. obex->tx_sent = 0;
  380. }
  381. if (obex->suspended) {
  382. obex->write_source = 0;
  383. return FALSE;
  384. }
  385. if (!obex->write(obex, NULL))
  386. goto stop_tx;
  387. done:
  388. if (obex->tx_data > 0 || g_queue_get_length(obex->tx_queue) > 0)
  389. return TRUE;
  390. stop_tx:
  391. obex->rx_last_op = G_OBEX_OP_NONE;
  392. obex->tx_data = 0;
  393. obex->write_source = 0;
  394. return FALSE;
  395. }
  396. static void enable_tx(GObex *obex)
  397. {
  398. GIOCondition cond;
  399. if (obex->suspended)
  400. return;
  401. if (!obex->io || obex->write_source > 0)
  402. return;
  403. cond = G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
  404. obex->write_source = g_io_add_watch(obex->io, cond, write_data, obex);
  405. }
  406. void g_obex_drop_tx_queue(GObex *obex)
  407. {
  408. struct pending_pkt *p;
  409. g_obex_debug(G_OBEX_DEBUG_COMMAND, "");
  410. while ((p = g_queue_pop_head(obex->tx_queue)))
  411. pending_pkt_free(p);
  412. }
  413. static gboolean g_obex_send_internal(GObex *obex, struct pending_pkt *p,
  414. GError **err)
  415. {
  416. if (obex->io == NULL) {
  417. if (!err)
  418. return FALSE;
  419. g_set_error(err, G_OBEX_ERROR, G_OBEX_ERROR_DISCONNECTED,
  420. "The transport is not connected");
  421. g_obex_debug(G_OBEX_DEBUG_ERROR, "%s", (*err)->message);
  422. return FALSE;
  423. }
  424. if (g_obex_packet_get_operation(p->pkt, NULL) == G_OBEX_OP_ABORT)
  425. g_queue_push_head(obex->tx_queue, p);
  426. else
  427. g_queue_push_tail(obex->tx_queue, p);
  428. if (obex->pending_req == NULL || p->id == 0)
  429. enable_tx(obex);
  430. return TRUE;
  431. }
  432. static void init_connect_data(GObex *obex, struct connect_data *data)
  433. {
  434. guint16 u16;
  435. memset(data, 0, sizeof(*data));
  436. data->version = 0x10;
  437. data->flags = 0;
  438. u16 = g_htons(obex->rx_mtu);
  439. memcpy(&data->mtu, &u16, sizeof(u16));
  440. }
  441. static guint8 *digest_response(const guint8 *nonce)
  442. {
  443. GChecksum *md5;
  444. guint8 *result;
  445. gsize size;
  446. result = g_new0(guint8, NONCE_LEN);
  447. md5 = g_checksum_new(G_CHECKSUM_MD5);
  448. if (md5 == NULL)
  449. return result;
  450. g_checksum_update(md5, nonce, NONCE_LEN);
  451. g_checksum_update(md5, (guint8 *) ":BlueZ", 6);
  452. size = NONCE_LEN;
  453. g_checksum_get_digest(md5, result, &size);
  454. g_checksum_free(md5);
  455. return result;
  456. }
  457. static void prepare_auth_rsp(GObex *obex, GObexPacket *rsp)
  458. {
  459. GObexHeader *hdr;
  460. GObexApparam *authrsp;
  461. const guint8 *nonce;
  462. guint8 *result;
  463. gsize len;
  464. /* Check if client is already responding to authentication challenge */
  465. hdr = g_obex_packet_get_header(rsp, G_OBEX_HDR_AUTHRESP);
  466. if (hdr)
  467. goto done;
  468. if (!g_obex_apparam_get_bytes(obex->authchal, NONCE_TAG, &nonce, &len))
  469. goto done;
  470. if (len != NONCE_LEN)
  471. goto done;
  472. result = digest_response(nonce);
  473. authrsp = g_obex_apparam_set_bytes(NULL, DIGEST_TAG, result, NONCE_LEN);
  474. hdr = g_obex_header_new_tag(G_OBEX_HDR_AUTHRESP, authrsp);
  475. g_obex_packet_add_header(rsp, hdr);
  476. g_obex_apparam_free(authrsp);
  477. g_free(result);
  478. done:
  479. g_obex_apparam_free(obex->authchal);
  480. obex->authchal = NULL;
  481. }
  482. static void prepare_connect_rsp(GObex *obex, GObexPacket *rsp)
  483. {
  484. GObexHeader *hdr;
  485. struct connect_data data;
  486. static guint32 next_connid = 1;
  487. init_connect_data(obex, &data);
  488. g_obex_packet_set_data(rsp, &data, sizeof(data), G_OBEX_DATA_COPY);
  489. hdr = g_obex_packet_get_header(rsp, G_OBEX_HDR_CONNECTION);
  490. if (hdr) {
  491. g_obex_header_get_uint32(hdr, &obex->conn_id);
  492. goto done;
  493. }
  494. obex->conn_id = next_connid++;
  495. hdr = g_obex_header_new_uint32(G_OBEX_HDR_CONNECTION, obex->conn_id);
  496. g_obex_packet_prepend_header(rsp, hdr);
  497. done:
  498. if (obex->authchal)
  499. prepare_auth_rsp(obex, rsp);
  500. }
  501. static void prepare_srm_rsp(GObex *obex, GObexPacket *pkt)
  502. {
  503. GObexHeader *hdr;
  504. if (!obex->use_srm || obex->srm == NULL)
  505. return;
  506. if (obex->srm->enabled)
  507. return;
  508. hdr = g_obex_packet_get_header(pkt, G_OBEX_HDR_SRM);
  509. if (hdr != NULL)
  510. return;
  511. hdr = g_obex_header_new_uint8(G_OBEX_HDR_SRM, G_OBEX_SRM_ENABLE);
  512. g_obex_packet_prepend_header(pkt, hdr);
  513. }
  514. gboolean g_obex_send(GObex *obex, GObexPacket *pkt, GError **err)
  515. {
  516. struct pending_pkt *p;
  517. gboolean ret;
  518. g_obex_debug(G_OBEX_DEBUG_COMMAND, "conn %u", obex->conn_id);
  519. if (obex == NULL || pkt == NULL) {
  520. if (!err)
  521. return FALSE;
  522. g_set_error(err, G_OBEX_ERROR, G_OBEX_ERROR_INVALID_ARGS,
  523. "Invalid arguments");
  524. g_obex_debug(G_OBEX_DEBUG_ERROR, "%s", (*err)->message);
  525. return FALSE;
  526. }
  527. switch (obex->rx_last_op) {
  528. case G_OBEX_OP_CONNECT:
  529. prepare_connect_rsp(obex, pkt);
  530. break;
  531. case G_OBEX_OP_GET:
  532. case G_OBEX_OP_PUT:
  533. prepare_srm_rsp(obex, pkt);
  534. break;
  535. }
  536. p = g_new0(struct pending_pkt, 1);
  537. p->pkt = pkt;
  538. ret = g_obex_send_internal(obex, p, err);
  539. if (ret == FALSE)
  540. pending_pkt_free(p);
  541. return ret;
  542. }
  543. static void prepare_srm_req(GObex *obex, GObexPacket *pkt)
  544. {
  545. GObexHeader *hdr;
  546. if (!obex->use_srm)
  547. return;
  548. if (obex->srm != NULL && obex->srm->enabled)
  549. return;
  550. hdr = g_obex_packet_get_header(pkt, G_OBEX_HDR_SRM);
  551. if (hdr != NULL)
  552. return;
  553. hdr = g_obex_header_new_uint8(G_OBEX_HDR_SRM, G_OBEX_SRM_ENABLE);
  554. g_obex_packet_prepend_header(pkt, hdr);
  555. }
  556. guint g_obex_send_req(GObex *obex, GObexPacket *req, int timeout,
  557. GObexResponseFunc func, gpointer user_data,
  558. GError **err)
  559. {
  560. GObexHeader *hdr;
  561. struct pending_pkt *p;
  562. static guint id = 1;
  563. guint8 op;
  564. g_obex_debug(G_OBEX_DEBUG_COMMAND, "conn %u", obex->conn_id);
  565. op = g_obex_packet_get_operation(req, NULL);
  566. if (op == G_OBEX_OP_PUT || op == G_OBEX_OP_GET) {
  567. /* Only enable SRM automatically for GET and PUT */
  568. prepare_srm_req(obex, req);
  569. }
  570. if (obex->conn_id == CONNID_INVALID)
  571. goto create_pending;
  572. if (obex->rx_last_op == G_OBEX_RSP_CONTINUE)
  573. goto create_pending;
  574. if (g_obex_srm_enabled(obex) && obex->pending_req != NULL)
  575. goto create_pending;
  576. hdr = g_obex_packet_get_header(req, G_OBEX_HDR_CONNECTION);
  577. if (hdr != NULL)
  578. goto create_pending;
  579. hdr = g_obex_header_new_uint32(G_OBEX_HDR_CONNECTION, obex->conn_id);
  580. g_obex_packet_prepend_header(req, hdr);
  581. create_pending:
  582. p = g_new0(struct pending_pkt, 1);
  583. p->pkt = req;
  584. p->id = id++;
  585. p->rsp_func = func;
  586. p->rsp_data = user_data;
  587. if (timeout < 0)
  588. p->timeout = G_OBEX_DEFAULT_TIMEOUT;
  589. else
  590. p->timeout = timeout;
  591. if (!g_obex_send_internal(obex, p, err)) {
  592. pending_pkt_free(p);
  593. return 0;
  594. }
  595. return p->id;
  596. }
  597. static int pending_pkt_cmp(gconstpointer a, gconstpointer b)
  598. {
  599. const struct pending_pkt *p = a;
  600. guint id = GPOINTER_TO_UINT(b);
  601. return (p->id - id);
  602. }
  603. static gboolean pending_req_abort(GObex *obex, GError **err)
  604. {
  605. struct pending_pkt *p = obex->pending_req;
  606. GObexPacket *req;
  607. if (p->cancelled)
  608. return TRUE;
  609. p->cancelled = TRUE;
  610. if (p->timeout_id > 0)
  611. g_source_remove(p->timeout_id);
  612. p->timeout = G_OBEX_ABORT_TIMEOUT;
  613. p->timeout_id = g_timeout_add_seconds(p->timeout, req_timeout, obex);
  614. req = g_obex_packet_new(G_OBEX_OP_ABORT, TRUE, G_OBEX_HDR_INVALID);
  615. return g_obex_send(obex, req, err);
  616. }
  617. static gboolean cancel_complete(gpointer user_data)
  618. {
  619. struct pending_pkt *p = user_data;
  620. GObex *obex = p->obex;
  621. GError *err;
  622. g_assert(p->rsp_func != NULL);
  623. err = g_error_new(G_OBEX_ERROR, G_OBEX_ERROR_CANCELLED,
  624. "The request was cancelled");
  625. p->rsp_func(obex, err, NULL, p->rsp_data);
  626. g_error_free(err);
  627. pending_pkt_free(p);
  628. return FALSE;
  629. }
  630. gboolean g_obex_cancel_req(GObex *obex, guint req_id, gboolean remove_callback)
  631. {
  632. GList *match;
  633. struct pending_pkt *p;
  634. if (obex->pending_req && obex->pending_req->id == req_id) {
  635. if (!pending_req_abort(obex, NULL)) {
  636. p = obex->pending_req;
  637. obex->pending_req = NULL;
  638. goto immediate_completion;
  639. }
  640. if (remove_callback)
  641. obex->pending_req->rsp_func = NULL;
  642. return TRUE;
  643. }
  644. match = g_queue_find_custom(obex->tx_queue, GUINT_TO_POINTER(req_id),
  645. pending_pkt_cmp);
  646. if (match == NULL)
  647. return FALSE;
  648. p = match->data;
  649. g_queue_delete_link(obex->tx_queue, match);
  650. immediate_completion:
  651. p->cancelled = TRUE;
  652. p->obex = g_obex_ref(obex);
  653. if (remove_callback || p->rsp_func == NULL)
  654. pending_pkt_free(p);
  655. else
  656. g_idle_add(cancel_complete, p);
  657. return TRUE;
  658. }
  659. gboolean g_obex_send_rsp(GObex *obex, guint8 rspcode, GError **err,
  660. guint first_hdr_type, ...)
  661. {
  662. GObexPacket *rsp;
  663. va_list args;
  664. va_start(args, first_hdr_type);
  665. rsp = g_obex_packet_new_valist(rspcode, TRUE, first_hdr_type, args);
  666. va_end(args);
  667. return g_obex_send(obex, rsp, err);
  668. }
  669. void g_obex_set_disconnect_function(GObex *obex, GObexFunc func,
  670. gpointer user_data)
  671. {
  672. obex->disconn_func = func;
  673. obex->disconn_func_data = user_data;
  674. }
  675. static int req_handler_cmpop(gconstpointer a, gconstpointer b)
  676. {
  677. const struct req_handler *handler = a;
  678. guint opcode = GPOINTER_TO_UINT(b);
  679. return (int) handler->opcode - (int) opcode;
  680. }
  681. static int req_handler_cmpid(gconstpointer a, gconstpointer b)
  682. {
  683. const struct req_handler *handler = a;
  684. guint id = GPOINTER_TO_UINT(b);
  685. return (int) handler->id - (int) id;
  686. }
  687. guint g_obex_add_request_function(GObex *obex, guint8 opcode,
  688. GObexRequestFunc func,
  689. gpointer user_data)
  690. {
  691. struct req_handler *handler;
  692. static guint next_id = 1;
  693. handler = g_new0(struct req_handler, 1);
  694. handler->id = next_id++;
  695. handler->opcode = opcode;
  696. handler->func = func;
  697. handler->user_data = user_data;
  698. obex->req_handlers = g_slist_prepend(obex->req_handlers, handler);
  699. return handler->id;
  700. }
  701. gboolean g_obex_remove_request_function(GObex *obex, guint id)
  702. {
  703. struct req_handler *handler;
  704. GSList *match;
  705. match = g_slist_find_custom(obex->req_handlers, GUINT_TO_POINTER(id),
  706. req_handler_cmpid);
  707. if (match == NULL)
  708. return FALSE;
  709. handler = match->data;
  710. obex->req_handlers = g_slist_delete_link(obex->req_handlers, match);
  711. g_free(handler);
  712. return TRUE;
  713. }
  714. static void g_obex_srm_suspend(GObex *obex)
  715. {
  716. struct pending_pkt *p = obex->pending_req;
  717. GObexPacket *req;
  718. if (p->timeout_id > 0) {
  719. g_source_remove(p->timeout_id);
  720. p->timeout_id = 0;
  721. }
  722. p->suspended = TRUE;
  723. req = g_obex_packet_new(G_OBEX_OP_GET, TRUE,
  724. G_OBEX_HDR_SRMP, G_OBEX_SRMP_WAIT,
  725. G_OBEX_HDR_INVALID);
  726. g_obex_send(obex, req, NULL);
  727. }
  728. void g_obex_suspend(GObex *obex)
  729. {
  730. struct pending_pkt *req = obex->pending_req;
  731. g_obex_debug(G_OBEX_DEBUG_COMMAND, "conn %u", obex->conn_id);
  732. if (!g_obex_srm_active(obex) || !req)
  733. goto done;
  734. /* Send SRMP wait in case of GET */
  735. if (g_obex_packet_get_operation(req->pkt, NULL) == G_OBEX_OP_GET) {
  736. g_obex_srm_suspend(obex);
  737. return;
  738. }
  739. done:
  740. obex->suspended = TRUE;
  741. if (obex->write_source > 0) {
  742. g_source_remove(obex->write_source);
  743. obex->write_source = 0;
  744. }
  745. }
  746. static void g_obex_srm_resume(GObex *obex)
  747. {
  748. struct pending_pkt *p = obex->pending_req;
  749. GObexPacket *req;
  750. p->timeout_id = g_timeout_add_seconds(p->timeout, req_timeout, obex);
  751. p->suspended = FALSE;
  752. req = g_obex_packet_new(G_OBEX_OP_GET, TRUE, G_OBEX_HDR_INVALID);
  753. g_obex_send(obex, req, NULL);
  754. }
  755. void g_obex_resume(GObex *obex)
  756. {
  757. struct pending_pkt *req = obex->pending_req;
  758. g_obex_debug(G_OBEX_DEBUG_COMMAND, "conn %u", obex->conn_id);
  759. obex->suspended = FALSE;
  760. if (g_obex_srm_active(obex) || !req)
  761. goto done;
  762. if (g_obex_packet_get_operation(req->pkt, NULL) == G_OBEX_OP_GET)
  763. g_obex_srm_resume(obex);
  764. done:
  765. if (g_queue_get_length(obex->tx_queue) > 0 || obex->tx_data > 0)
  766. enable_tx(obex);
  767. }
  768. gboolean g_obex_srm_active(GObex *obex)
  769. {
  770. gboolean ret = FALSE;
  771. if (!g_obex_srm_enabled(obex))
  772. goto done;
  773. if (obex->srm->srmp <= G_OBEX_SRMP_NEXT_WAIT)
  774. goto done;
  775. ret = TRUE;
  776. done:
  777. g_obex_debug(G_OBEX_DEBUG_COMMAND, "%s", ret ? "yes" : "no");
  778. return ret;
  779. }
  780. static void auth_challenge(GObex *obex)
  781. {
  782. struct pending_pkt *p = obex->pending_req;
  783. if (p->authenticating)
  784. return;
  785. p->authenticating = TRUE;
  786. prepare_auth_rsp(obex, p->pkt);
  787. /* Remove it as pending and add it back to the queue so it gets sent
  788. * again */
  789. if (p->timeout_id > 0) {
  790. g_source_remove(p->timeout_id);
  791. p->timeout_id = 0;
  792. }
  793. obex->pending_req = NULL;
  794. g_obex_send_internal(obex, p, NULL);
  795. }
  796. static void parse_connect_data(GObex *obex, GObexPacket *pkt)
  797. {
  798. const struct connect_data *data;
  799. GObexHeader *hdr;
  800. guint16 u16;
  801. size_t data_len;
  802. data = g_obex_packet_get_data(pkt, &data_len);
  803. if (data == NULL || data_len != sizeof(*data))
  804. return;
  805. memcpy(&u16, &data->mtu, sizeof(u16));
  806. obex->tx_mtu = g_ntohs(u16);
  807. if (obex->io_tx_mtu > 0 && obex->tx_mtu > obex->io_tx_mtu)
  808. obex->tx_mtu = obex->io_tx_mtu;
  809. obex->tx_buf = g_realloc(obex->tx_buf, obex->tx_mtu);
  810. hdr = g_obex_packet_get_header(pkt, G_OBEX_HDR_CONNECTION);
  811. if (hdr)
  812. g_obex_header_get_uint32(hdr, &obex->conn_id);
  813. hdr = g_obex_packet_get_header(pkt, G_OBEX_HDR_AUTHCHAL);
  814. if (hdr)
  815. obex->authchal = g_obex_header_get_apparam(hdr);
  816. }
  817. static gboolean parse_response(GObex *obex, GObexPacket *rsp)
  818. {
  819. struct pending_pkt *p = obex->pending_req;
  820. guint8 opcode, rspcode;
  821. gboolean final;
  822. rspcode = g_obex_packet_get_operation(rsp, &final);
  823. opcode = g_obex_packet_get_operation(p->pkt, NULL);
  824. if (opcode == G_OBEX_OP_CONNECT) {
  825. parse_connect_data(obex, rsp);
  826. if (rspcode == G_OBEX_RSP_UNAUTHORIZED && obex->authchal)
  827. auth_challenge(obex);
  828. }
  829. setup_srm(obex, rsp, FALSE);
  830. if (!g_obex_srm_enabled(obex))
  831. return final;
  832. /*
  833. * Resposes have final bit set but in case of GET with SRM
  834. * we should not remove the request since the remote side will
  835. * continue sending responses until the transfer is finished
  836. */
  837. if (opcode == G_OBEX_OP_GET && rspcode == G_OBEX_RSP_CONTINUE) {
  838. if (p->timeout_id > 0)
  839. g_source_remove(p->timeout_id);
  840. p->timeout_id = g_timeout_add_seconds(p->timeout, req_timeout,
  841. obex);
  842. return FALSE;
  843. }
  844. return final;
  845. }
  846. static void handle_response(GObex *obex, GError *err, GObexPacket *rsp)
  847. {
  848. struct pending_pkt *p;
  849. gboolean disconn = err ? TRUE : FALSE, final_rsp = TRUE;
  850. if (rsp != NULL)
  851. final_rsp = parse_response(obex, rsp);
  852. if (!obex->pending_req)
  853. return;
  854. p = obex->pending_req;
  855. /* Reset if final so it can no longer be cancelled */
  856. if (final_rsp)
  857. obex->pending_req = NULL;
  858. if (p->cancelled)
  859. err = g_error_new(G_OBEX_ERROR, G_OBEX_ERROR_CANCELLED,
  860. "The operation was cancelled");
  861. if (err)
  862. g_obex_debug(G_OBEX_DEBUG_ERROR, "%s", err->message);
  863. if (p->rsp_func) {
  864. p->rsp_func(obex, err, rsp, p->rsp_data);
  865. /* Check if user callback removed the request */
  866. if (!final_rsp && p != obex->pending_req)
  867. return;
  868. }
  869. if (p->cancelled)
  870. g_error_free(err);
  871. if (final_rsp)
  872. pending_pkt_free(p);
  873. if (!disconn && g_queue_get_length(obex->tx_queue) > 0)
  874. enable_tx(obex);
  875. }
  876. static gboolean check_connid(GObex *obex, GObexPacket *pkt)
  877. {
  878. GObexHeader *hdr;
  879. guint32 id;
  880. if (obex->conn_id == CONNID_INVALID)
  881. return TRUE;
  882. hdr = g_obex_packet_get_header(pkt, G_OBEX_HDR_CONNECTION);
  883. if (hdr == NULL)
  884. return TRUE;
  885. g_obex_header_get_uint32(hdr, &id);
  886. return obex->conn_id == id;
  887. }
  888. static int parse_request(GObex *obex, GObexPacket *req)
  889. {
  890. guint8 op;
  891. gboolean final;
  892. op = g_obex_packet_get_operation(req, &final);
  893. switch (op) {
  894. case G_OBEX_OP_CONNECT:
  895. parse_connect_data(obex, req);
  896. break;
  897. case G_OBEX_OP_ABORT:
  898. break;
  899. default:
  900. if (check_connid(obex, req))
  901. break;
  902. return -G_OBEX_RSP_SERVICE_UNAVAILABLE;
  903. }
  904. setup_srm(obex, req, FALSE);
  905. return op;
  906. }
  907. static void handle_request(GObex *obex, GObexPacket *req)
  908. {
  909. GSList *match;
  910. int op;
  911. op = parse_request(obex, req);
  912. if (op < 0)
  913. goto fail;
  914. match = g_slist_find_custom(obex->req_handlers, GUINT_TO_POINTER(op),
  915. req_handler_cmpop);
  916. if (match) {
  917. struct req_handler *handler = match->data;
  918. handler->func(obex, req, handler->user_data);
  919. return;
  920. }
  921. op = -G_OBEX_RSP_NOT_IMPLEMENTED;
  922. fail:
  923. g_obex_debug(G_OBEX_DEBUG_ERROR, "%s", g_obex_strerror(-op));
  924. g_obex_send_rsp(obex, -op, NULL, G_OBEX_HDR_INVALID);
  925. }
  926. static gboolean read_stream(GObex *obex, GError **err)
  927. {
  928. GIOChannel *io = obex->io;
  929. GIOStatus status;
  930. gsize rbytes, toread;
  931. guint16 u16;
  932. char *buf;
  933. if (obex->rx_data >= 3)
  934. goto read_body;
  935. rbytes = 0;
  936. toread = 3 - obex->rx_data;
  937. buf = (char *) &obex->rx_buf[obex->rx_data];
  938. status = g_io_channel_read_chars(io, buf, toread, &rbytes, NULL);
  939. if (status != G_IO_STATUS_NORMAL)
  940. return TRUE;
  941. obex->rx_data += rbytes;
  942. if (obex->rx_data < 3)
  943. goto done;
  944. memcpy(&u16, &buf[1], sizeof(u16));
  945. obex->rx_pkt_len = g_ntohs(u16);
  946. if (obex->rx_pkt_len > obex->rx_mtu) {
  947. if (!err)
  948. return FALSE;
  949. g_set_error(err, G_OBEX_ERROR, G_OBEX_ERROR_PARSE_ERROR,
  950. "Too big incoming packet");
  951. g_obex_debug(G_OBEX_DEBUG_ERROR, "%s", (*err)->message);
  952. return FALSE;
  953. }
  954. read_body:
  955. if (obex->rx_data >= obex->rx_pkt_len)
  956. goto done;
  957. do {
  958. toread = obex->rx_pkt_len - obex->rx_data;
  959. buf = (char *) &obex->rx_buf[obex->rx_data];
  960. status = g_io_channel_read_chars(io, buf, toread, &rbytes, NULL);
  961. if (status != G_IO_STATUS_NORMAL)
  962. goto done;
  963. obex->rx_data += rbytes;
  964. } while (rbytes > 0 && obex->rx_data < obex->rx_pkt_len);
  965. done:
  966. g_obex_dump(G_OBEX_DEBUG_DATA, ">", obex->rx_buf, obex->rx_data);
  967. return TRUE;
  968. }
  969. static gboolean read_packet(GObex *obex, GError **err)
  970. {
  971. GIOChannel *io = obex->io;
  972. GError *read_err = NULL;
  973. GIOStatus status;
  974. gsize rbytes;
  975. guint16 u16;
  976. if (obex->rx_data > 0) {
  977. g_set_error(err, G_OBEX_ERROR, G_OBEX_ERROR_PARSE_ERROR,
  978. "RX buffer not empty before reading packet");
  979. goto fail;
  980. }
  981. status = g_io_channel_read_chars(io, (char *) obex->rx_buf,
  982. obex->rx_mtu, &rbytes, &read_err);
  983. if (status != G_IO_STATUS_NORMAL) {
  984. g_set_error(err, G_OBEX_ERROR, G_OBEX_ERROR_PARSE_ERROR,
  985. "Unable to read data: %s", read_err->message);
  986. g_error_free(read_err);
  987. goto fail;
  988. }
  989. obex->rx_data += rbytes;
  990. if (rbytes < 3) {
  991. g_set_error(err, G_OBEX_ERROR, G_OBEX_ERROR_PARSE_ERROR,
  992. "Incomplete packet received");
  993. goto fail;
  994. }
  995. memcpy(&u16, &obex->rx_buf[1], sizeof(u16));
  996. obex->rx_pkt_len = g_ntohs(u16);
  997. if (obex->rx_pkt_len != rbytes) {
  998. g_set_error(err, G_OBEX_ERROR, G_OBEX_ERROR_PARSE_ERROR,
  999. "Data size doesn't match packet size (%zu != %u)",
  1000. rbytes, obex->rx_pkt_len);
  1001. return FALSE;
  1002. }
  1003. g_obex_dump(G_OBEX_DEBUG_DATA, ">", obex->rx_buf, obex->rx_data);
  1004. return TRUE;
  1005. fail:
  1006. if (err)
  1007. g_obex_debug(G_OBEX_DEBUG_ERROR, "%s", (*err)->message);
  1008. return FALSE;
  1009. }
  1010. static gboolean incoming_data(GIOChannel *io, GIOCondition cond,
  1011. gpointer user_data)
  1012. {
  1013. GObex *obex = user_data;
  1014. GObexPacket *pkt;
  1015. ssize_t header_offset;
  1016. GError *err = NULL;
  1017. guint8 opcode;
  1018. if (cond & G_IO_NVAL)
  1019. return FALSE;
  1020. if (cond & (G_IO_HUP | G_IO_ERR)) {
  1021. err = g_error_new(G_OBEX_ERROR, G_OBEX_ERROR_DISCONNECTED,
  1022. "Transport got disconnected");
  1023. goto failed;
  1024. }
  1025. if (!obex->read(obex, &err))
  1026. goto failed;
  1027. if (obex->rx_data < 3 || obex->rx_data < obex->rx_pkt_len)
  1028. return TRUE;
  1029. obex->rx_last_op = obex->rx_buf[0] & ~FINAL_BIT;
  1030. if (obex->pending_req) {
  1031. struct pending_pkt *p = obex->pending_req;
  1032. opcode = g_obex_packet_get_operation(p->pkt, NULL);
  1033. header_offset = rsp_header_offset(opcode);
  1034. } else {
  1035. opcode = obex->rx_last_op;
  1036. /* Unexpected response -- fail silently */
  1037. if (opcode > 0x1f && opcode != G_OBEX_OP_ABORT) {
  1038. obex->rx_data = 0;
  1039. return TRUE;
  1040. }
  1041. header_offset = req_header_offset(opcode);
  1042. }
  1043. if (header_offset < 0) {
  1044. err = g_error_new(G_OBEX_ERROR, G_OBEX_ERROR_PARSE_ERROR,
  1045. "Unknown header offset for opcode 0x%02x",
  1046. opcode);
  1047. goto failed;
  1048. }
  1049. pkt = g_obex_packet_decode(obex->rx_buf, obex->rx_data, header_offset,
  1050. G_OBEX_DATA_REF, &err);
  1051. if (pkt == NULL)
  1052. goto failed;
  1053. /* Protect against user callback freeing the object */
  1054. g_obex_ref(obex);
  1055. if (obex->pending_req)
  1056. handle_response(obex, NULL, pkt);
  1057. else
  1058. handle_request(obex, pkt);
  1059. obex->rx_data = 0;
  1060. g_obex_unref(obex);
  1061. if (err != NULL)
  1062. g_error_free(err);
  1063. if (pkt != NULL)
  1064. g_obex_packet_free(pkt);
  1065. return TRUE;
  1066. failed:
  1067. if (err)
  1068. g_obex_debug(G_OBEX_DEBUG_ERROR, "%s", err->message);
  1069. g_io_channel_unref(obex->io);
  1070. obex->io = NULL;
  1071. obex->io_source = 0;
  1072. obex->rx_data = 0;
  1073. /* Protect against user callback freeing the object */
  1074. g_obex_ref(obex);
  1075. if (obex->pending_req)
  1076. handle_response(obex, err, NULL);
  1077. if (obex->disconn_func)
  1078. obex->disconn_func(obex, err, obex->disconn_func_data);
  1079. g_obex_unref(obex);
  1080. g_error_free(err);
  1081. return FALSE;
  1082. }
  1083. static GDebugKey keys[] = {
  1084. { "error", G_OBEX_DEBUG_ERROR },
  1085. { "command", G_OBEX_DEBUG_COMMAND },
  1086. { "transfer", G_OBEX_DEBUG_TRANSFER },
  1087. { "header", G_OBEX_DEBUG_HEADER },
  1088. { "packet", G_OBEX_DEBUG_PACKET },
  1089. { "data", G_OBEX_DEBUG_DATA },
  1090. { "apparam", G_OBEX_DEBUG_APPARAM },
  1091. };
  1092. GObex *g_obex_new(GIOChannel *io, GObexTransportType transport_type,
  1093. gssize io_rx_mtu, gssize io_tx_mtu)
  1094. {
  1095. GObex *obex;
  1096. GIOCondition cond;
  1097. if (gobex_debug == 0) {
  1098. const char *env = g_getenv("GOBEX_DEBUG");
  1099. if (env) {
  1100. gobex_debug = g_parse_debug_string(env, keys, 7);
  1101. g_setenv("G_MESSAGES_DEBUG", "gobex", FALSE);
  1102. } else
  1103. gobex_debug = G_OBEX_DEBUG_NONE;
  1104. }
  1105. g_obex_debug(G_OBEX_DEBUG_COMMAND, "");
  1106. if (io == NULL)
  1107. return NULL;
  1108. if (io_rx_mtu >= 0 && io_rx_mtu < G_OBEX_MINIMUM_MTU)
  1109. return NULL;
  1110. if (io_tx_mtu >= 0 && io_tx_mtu < G_OBEX_MINIMUM_MTU)
  1111. return NULL;
  1112. obex = g_new0(GObex, 1);
  1113. obex->io = g_io_channel_ref(io);
  1114. obex->ref_count = 1;
  1115. obex->conn_id = CONNID_INVALID;
  1116. obex->rx_last_op = G_OBEX_OP_NONE;
  1117. obex->io_rx_mtu = io_rx_mtu;
  1118. obex->io_tx_mtu = io_tx_mtu;
  1119. if (io_rx_mtu > G_OBEX_MAXIMUM_MTU)
  1120. obex->rx_mtu = G_OBEX_MAXIMUM_MTU;
  1121. else if (io_rx_mtu < G_OBEX_MINIMUM_MTU)
  1122. obex->rx_mtu = G_OBEX_DEFAULT_MTU;
  1123. else
  1124. obex->rx_mtu = io_rx_mtu;
  1125. obex->tx_mtu = G_OBEX_MINIMUM_MTU;
  1126. obex->tx_queue = g_queue_new();
  1127. obex->rx_buf = g_malloc(obex->rx_mtu);
  1128. obex->tx_buf = g_malloc(obex->tx_mtu);
  1129. switch (transport_type) {
  1130. case G_OBEX_TRANSPORT_STREAM:
  1131. obex->read = read_stream;
  1132. obex->write = write_stream;
  1133. break;
  1134. case G_OBEX_TRANSPORT_PACKET:
  1135. obex->use_srm = TRUE;
  1136. obex->read = read_packet;
  1137. obex->write = write_packet;
  1138. break;
  1139. default:
  1140. g_obex_unref(obex);
  1141. return NULL;
  1142. }
  1143. g_io_channel_set_encoding(io, NULL, NULL);
  1144. g_io_channel_set_buffered(io, FALSE);
  1145. cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
  1146. obex->io_source = g_io_add_watch(io, cond, incoming_data, obex);
  1147. return obex;
  1148. }
  1149. GObex *g_obex_ref(GObex *obex)
  1150. {
  1151. int refs;
  1152. if (obex == NULL)
  1153. return NULL;
  1154. refs = __sync_add_and_fetch(&obex->ref_count, 1);
  1155. g_obex_debug(G_OBEX_DEBUG_COMMAND, "ref %u", refs);
  1156. return obex;
  1157. }
  1158. static void tx_queue_free(void *data, void *user_data)
  1159. {
  1160. pending_pkt_free(data);
  1161. }
  1162. void g_obex_unref(GObex *obex)
  1163. {
  1164. int refs;
  1165. refs = __sync_sub_and_fetch(&obex->ref_count, 1);
  1166. g_obex_debug(G_OBEX_DEBUG_COMMAND, "ref %u", refs);
  1167. if (refs > 0)
  1168. return;
  1169. g_slist_free_full(obex->req_handlers, g_free);
  1170. g_queue_foreach(obex->tx_queue, tx_queue_free, NULL);
  1171. g_queue_free(obex->tx_queue);
  1172. if (obex->io != NULL)
  1173. g_io_channel_unref(obex->io);
  1174. if (obex->io_source > 0)
  1175. g_source_remove(obex->io_source);
  1176. if (obex->write_source > 0)
  1177. g_source_remove(obex->write_source);
  1178. g_free(obex->rx_buf);
  1179. g_free(obex->tx_buf);
  1180. g_free(obex->srm);
  1181. if (obex->pending_req)
  1182. pending_pkt_free(obex->pending_req);
  1183. if (obex->authchal)
  1184. g_obex_apparam_free(obex->authchal);
  1185. g_free(obex);
  1186. }
  1187. /* Higher level functions */
  1188. guint g_obex_connect(GObex *obex, GObexResponseFunc func, gpointer user_data,
  1189. GError **err, guint first_hdr_id, ...)
  1190. {
  1191. GObexPacket *req;
  1192. struct connect_data data;
  1193. va_list args;
  1194. g_obex_debug(G_OBEX_DEBUG_COMMAND, "");
  1195. va_start(args, first_hdr_id);
  1196. req = g_obex_packet_new_valist(G_OBEX_OP_CONNECT, TRUE,
  1197. first_hdr_id, args);
  1198. va_end(args);
  1199. init_connect_data(obex, &data);
  1200. g_obex_packet_set_data(req, &data, sizeof(data), G_OBEX_DATA_COPY);
  1201. return g_obex_send_req(obex, req, -1, func, user_data, err);
  1202. }
  1203. guint g_obex_disconnect(GObex *obex, GObexResponseFunc func, gpointer user_data,
  1204. GError **err)
  1205. {
  1206. GObexPacket *req;
  1207. g_obex_debug(G_OBEX_DEBUG_COMMAND, "");
  1208. req = g_obex_packet_new(G_OBEX_OP_DISCONNECT, TRUE, G_OBEX_HDR_INVALID);
  1209. return g_obex_send_req(obex, req, -1, func, user_data, err);
  1210. }
  1211. guint g_obex_setpath(GObex *obex, const char *path, GObexResponseFunc func,
  1212. gpointer user_data, GError **err)
  1213. {
  1214. GObexPacket *req;
  1215. struct setpath_data data;
  1216. const char *folder;
  1217. g_obex_debug(G_OBEX_DEBUG_COMMAND, "conn %u", obex->conn_id);
  1218. req = g_obex_packet_new(G_OBEX_OP_SETPATH, TRUE, G_OBEX_HDR_INVALID);
  1219. memset(&data, 0, sizeof(data));
  1220. if (path != NULL && strncmp("..", path, 2) == 0) {
  1221. data.flags = 0x03;
  1222. folder = (path[2] == '/') ? &path[3] : NULL;
  1223. } else {
  1224. data.flags = 0x02;
  1225. folder = path;
  1226. }
  1227. if (folder != NULL) {
  1228. GObexHeader *hdr;
  1229. hdr = g_obex_header_new_unicode(G_OBEX_HDR_NAME, folder);
  1230. g_obex_packet_add_header(req, hdr);
  1231. }
  1232. g_obex_packet_set_data(req, &data, sizeof(data), G_OBEX_DATA_COPY);
  1233. return g_obex_send_req(obex, req, -1, func, user_data, err);
  1234. }
  1235. guint g_obex_mkdir(GObex *obex, const char *path, GObexResponseFunc func,
  1236. gpointer user_data, GError **err)
  1237. {
  1238. GObexPacket *req;
  1239. struct setpath_data data;
  1240. g_obex_debug(G_OBEX_DEBUG_COMMAND, "conn %u", obex->conn_id);
  1241. req = g_obex_packet_new(G_OBEX_OP_SETPATH, TRUE, G_OBEX_HDR_NAME, path,
  1242. G_OBEX_HDR_INVALID);
  1243. memset(&data, 0, sizeof(data));
  1244. g_obex_packet_set_data(req, &data, sizeof(data), G_OBEX_DATA_COPY);
  1245. return g_obex_send_req(obex, req, -1, func, user_data, err);
  1246. }
  1247. guint g_obex_delete(GObex *obex, const char *name, GObexResponseFunc func,
  1248. gpointer user_data, GError **err)
  1249. {
  1250. GObexPacket *req;
  1251. g_obex_debug(G_OBEX_DEBUG_COMMAND, "conn %u", obex->conn_id);
  1252. req = g_obex_packet_new(G_OBEX_OP_PUT, TRUE, G_OBEX_HDR_NAME, name,
  1253. G_OBEX_HDR_INVALID);
  1254. return g_obex_send_req(obex, req, -1, func, user_data, err);
  1255. }
  1256. guint g_obex_copy(GObex *obex, const char *name, const char *dest,
  1257. GObexResponseFunc func, gpointer user_data,
  1258. GError **err)
  1259. {
  1260. GObexPacket *req;
  1261. g_obex_debug(G_OBEX_DEBUG_COMMAND, "conn %u", obex->conn_id);
  1262. req = g_obex_packet_new(G_OBEX_OP_ACTION, TRUE,
  1263. G_OBEX_HDR_ACTION, G_OBEX_ACTION_COPY,
  1264. G_OBEX_HDR_NAME, name,
  1265. G_OBEX_HDR_DESTNAME, dest,
  1266. G_OBEX_HDR_INVALID);
  1267. return g_obex_send_req(obex, req, -1, func, user_data, err);
  1268. }
  1269. guint g_obex_move(GObex *obex, const char *name, const char *dest,
  1270. GObexResponseFunc func, gpointer user_data,
  1271. GError **err)
  1272. {
  1273. GObexPacket *req;
  1274. g_obex_debug(G_OBEX_DEBUG_COMMAND, "conn %u", obex->conn_id);
  1275. req = g_obex_packet_new(G_OBEX_OP_ACTION, TRUE,
  1276. G_OBEX_HDR_ACTION, G_OBEX_ACTION_MOVE,
  1277. G_OBEX_HDR_NAME, name,
  1278. G_OBEX_HDR_DESTNAME, dest,
  1279. G_OBEX_HDR_INVALID);
  1280. return g_obex_send_req(obex, req, -1, func, user_data, err);
  1281. }
  1282. guint g_obex_abort(GObex *obex, GObexResponseFunc func, gpointer user_data,
  1283. GError **err)
  1284. {
  1285. GObexPacket *req;
  1286. req = g_obex_packet_new(G_OBEX_OP_ABORT, TRUE, G_OBEX_HDR_INVALID);
  1287. return g_obex_send_req(obex, req, -1, func, user_data, err);
  1288. }
  1289. guint8 g_obex_errno_to_rsp(int err)
  1290. {
  1291. switch (err) {
  1292. case 0:
  1293. return G_OBEX_RSP_SUCCESS;
  1294. case -EPERM:
  1295. case -EACCES:
  1296. return G_OBEX_RSP_FORBIDDEN;
  1297. case -ENOENT:
  1298. return G_OBEX_RSP_NOT_FOUND;
  1299. case -EINVAL:
  1300. case -EBADR:
  1301. return G_OBEX_RSP_BAD_REQUEST;
  1302. case -EFAULT:
  1303. return G_OBEX_RSP_SERVICE_UNAVAILABLE;
  1304. case -ENOSYS:
  1305. return G_OBEX_RSP_NOT_IMPLEMENTED;
  1306. case -ENOTEMPTY:
  1307. case -EEXIST:
  1308. return G_OBEX_RSP_PRECONDITION_FAILED;
  1309. default:
  1310. return G_OBEX_RSP_INTERNAL_SERVER_ERROR;
  1311. }
  1312. }