00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <libsyncml/syncml.h>
00023 #include <libsyncml/syncml_internals.h>
00024 #include <libsyncml/sml_error_internals.h>
00025
00026 #include <libsyncml/sml_transport_internals.h>
00027
00028 #include "obex_internals.h"
00029 #include "obex_server_internals.h"
00030
00031 #ifndef WIN32
00032 #include <fcntl.h>
00033 #include <sys/poll.h>
00034 #include <sys/stat.h>
00035 #include <sys/types.h>
00036 #include <termios.h>
00037 #include <sys/socket.h>
00038 #include <netinet/in.h>
00039 #include <netdb.h>
00040 #endif
00041
00042 static gboolean _dispatch_obex(gpointer data)
00043 {
00044 SmlLinkObexServerEnv *linkenv = data;
00045
00046 int result = OBEX_HandleInput(linkenv->handle, 0);
00047 if (result < 0) {
00048 SmlError *error = NULL;
00049 smlErrorSet(&error, SML_ERROR_GENERIC,
00050 "The handling of the obex input failed (%i).",
00051 result);
00052 smlTransportReceiveEvent(linkenv->env->tsp, linkenv->link, SML_TRANSPORT_EVENT_ERROR, NULL, error);
00053 smlTrace(TRACE_ERROR, "%s: %s", __func__, smlErrorPrint(&error));
00054 smlErrorDeref(&error);
00055 return FALSE;
00056 }
00057
00058 if (linkenv->disconnect) {
00059 smlTrace(TRACE_INTERNAL, "%s: disconnecting link", __func__);
00060 OBEX_TransportDisconnect(linkenv->handle);
00061
00062 linkenv->destroy = TRUE;
00063 }
00064
00065
00066 if (linkenv->destroy) {
00067 smlTrace(TRACE_INTERNAL, "%s: Destroying link %p %p", __func__, linkenv, linkenv->link);
00068
00069
00070 SmlTransport *tsp = linkenv->env->tsp;
00071 SmlLink *link_ = linkenv->link;
00072 smlLinkRef(link_);
00073
00074
00075 smlLinkDeref(linkenv->link);
00076 g_source_unref(linkenv->source);
00077 OBEX_Cleanup(linkenv->handle);
00078 if (tsp->context)
00079 g_main_context_unref(tsp->context);
00080 smlSafeFree((gpointer *)&linkenv);
00081 link_->link_data = NULL;
00082
00083
00084 smlTransportReceiveEvent(tsp, link_, SML_TRANSPORT_EVENT_DISCONNECT_DONE, NULL, NULL);
00085 smlLinkDeref(link_);
00086
00087 return FALSE;
00088 }
00089 return TRUE;
00090 }
00091
00092 static void _smlTransportObexServerLinkEvent(obex_t *handle, obex_object_t *object, int mode, int event, int obex_cmd, int obex_rsp)
00093 {
00094 smlTrace(TRACE_ENTRY, "%s(%p, %p, %i, %i, %i, %i)", __func__, handle, object, mode, event, obex_cmd, obex_rsp);
00095 SmlLinkObexServerEnv *linkenv = OBEX_GetUserData(handle);
00096 SmlError *error = NULL;
00097 obex_headerdata_t header;
00098 uint8_t headertype = 0;
00099 uint32_t len = 0;
00100 uint32_t conid = 0;
00101 SmlMimeType mimetype = SML_MIMETYPE_UNKNOWN;
00102
00103 if (linkenv->disconnect) {
00104 OBEX_ObjectSetRsp(object, OBEX_RSP_FORBIDDEN, OBEX_RSP_FORBIDDEN);
00105 smlTrace(TRACE_EXIT, "%s: This link was disconnected", __func__);
00106 return;
00107 }
00108
00109 switch (event) {
00110 case OBEX_EV_PROGRESS:
00111 smlTrace(TRACE_INTERNAL, "%s: Progress", __func__);
00112 break;
00113 case OBEX_EV_REQDONE:
00114 smlTrace(TRACE_INTERNAL, "%s: Done", __func__);
00115 if (obex_cmd == OBEX_CMD_DISCONNECT) {
00116 linkenv->destroy = TRUE;
00117 }
00118 break;
00119 case OBEX_EV_REQHINT:
00120 smlTrace(TRACE_INTERNAL, "%s: Hint", __func__);
00121
00122 switch (obex_cmd) {
00123 case OBEX_CMD_GET:
00124
00125
00126 while (!linkenv->send_data && !linkenv->disconnect && !linkenv->error) {
00127 if (!g_main_context_pending(linkenv->env->tsp->context)) {
00128 usleep(100);
00129 continue;
00130 }
00131 smlTrace(TRACE_INTERNAL, "%s: Dispatching command queue since we dont have data to send", __func__);
00132 g_main_context_iteration(linkenv->env->tsp->context, TRUE);
00133 }
00134
00135
00136 if (linkenv->disconnect) {
00137 OBEX_ObjectSetRsp(object, OBEX_RSP_FORBIDDEN, OBEX_RSP_FORBIDDEN);
00138 smlTrace(TRACE_INTERNAL, "%s: Get was aborted", __func__);
00139 break;
00140 }
00141 case OBEX_CMD_PUT:
00142 case OBEX_CMD_CONNECT:
00143 case OBEX_CMD_DISCONNECT:
00144 OBEX_ObjectSetRsp(object, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS);
00145 break;
00146 default:
00147 OBEX_ObjectSetRsp(object, OBEX_RSP_NOT_IMPLEMENTED, OBEX_RSP_NOT_IMPLEMENTED);
00148 break;
00149 }
00150 break;
00151 case OBEX_EV_REQ:
00152 switch (obex_cmd) {
00153 case OBEX_CMD_SETPATH:
00154 smlTrace(TRACE_INTERNAL, "%s: Got SETPATH command", __func__);
00155 OBEX_ObjectSetRsp(object, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS);
00156 break;
00157 case OBEX_CMD_PUT:;
00158 smlTrace(TRACE_INTERNAL, "%s: Got PUT command", __func__);
00159 uint32_t length = 0;
00160 char *body = NULL;
00161
00162 while (OBEX_ObjectGetNextHeader(handle, object, &headertype, &header, &len)) {
00163 smlTrace(TRACE_INTERNAL, "%s: Next header %i, %d, %p", __func__, headertype, header.bq4, header.bs);
00164 switch (headertype) {
00165 case OBEX_HDR_CONNECTION:
00166 smlTrace(TRACE_INTERNAL, "%s: Found connection number: %d", __func__, header.bq4);
00167 conid = header.bq4;
00168 break;
00169 case OBEX_HDR_TYPE:;
00170 char *mimetypestr = g_strndup((char *)header.bs, len);
00171
00172
00173
00174
00175
00176
00177
00178 smlTrace(TRACE_INTERNAL, "%s: Found type: %s", __func__, VA_STRING(mimetypestr));
00179
00180 if (!strcmp(mimetypestr, SML_ELEMENT_WBXML)) {
00181 mimetype = SML_MIMETYPE_WBXML;
00182 } else if (!strcmp(mimetypestr, SML_ELEMENT_XML)) {
00183 mimetype = SML_MIMETYPE_XML;
00184 } else if (!strcmp(mimetypestr, SML_ELEMENT_SAN)) {
00185 mimetype = SML_MIMETYPE_SAN;
00186 } else {
00187 smlSafeCFree(&mimetypestr);
00188 smlErrorSet(&error, SML_ERROR_GENERIC, "Unknown mime type");
00189 goto error;
00190 }
00191
00192 smlSafeCFree(&mimetypestr);
00193 break;
00194 case OBEX_HDR_LENGTH:
00195 smlTrace(TRACE_INTERNAL, "%s: Found length: %d", __func__, header.bq4);
00196 length = header.bq4;
00197 break;
00198 case OBEX_HDR_BODY:
00199 if (!length) {
00200 smlErrorSet(&error, SML_ERROR_GENERIC, "Length must come before the body");
00201 goto error;
00202 }
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212 body = smlTryMalloc0(length + 1, &error);
00213 if (!body)
00214 goto error;
00215
00216 memcpy(body, header.bs, length);
00217 break;
00218 default:
00219 smlTrace(TRACE_INTERNAL, "%s: Unknown header", __func__);
00220 }
00221 }
00222
00223 if (!conid) {
00224 smlErrorSet(&error, SML_ERROR_GENERIC, "Missing connection id");
00225 goto error;
00226 }
00227
00228 if (conid != linkenv->conid) {
00229 smlErrorSet(&error, SML_ERROR_GENERIC, "Wrong connection id");
00230 goto error;
00231 }
00232
00233 if (mimetype == SML_MIMETYPE_UNKNOWN) {
00234 smlErrorSet(&error, SML_ERROR_GENERIC, "Missing mime type");
00235 goto error;
00236 }
00237
00238 if (!length) {
00239 smlErrorSet(&error, SML_ERROR_GENERIC, "Missing length");
00240 goto error;
00241 }
00242
00243 if (!body) {
00244 smlErrorSet(&error, SML_ERROR_GENERIC, "Missing body");
00245 goto error;
00246 }
00247
00248 SmlTransportData *tspdata = smlTransportDataNew(body, length, mimetype, TRUE, &error);
00249 if (!tspdata)
00250 goto error;
00251
00252 if (smlTransportReceiveEvent(linkenv->env->tsp, linkenv->link, SML_TRANSPORT_EVENT_DATA, tspdata, NULL))
00253 OBEX_ObjectSetRsp(object, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS);
00254 else
00255 OBEX_ObjectSetRsp(object, OBEX_RSP_FORBIDDEN, OBEX_RSP_FORBIDDEN);
00256
00257 smlTransportDataDeref(tspdata);
00258 break;
00259 case OBEX_CMD_GET:;
00260 smlTrace(TRACE_INTERNAL, "%s: Got GET command", __func__);
00261
00262 while (OBEX_ObjectGetNextHeader(handle, object, &headertype, &header, &len)) {
00263 smlTrace(TRACE_INTERNAL, "%s: Next header %i, %d, %p", __func__, headertype, header.bq4, header.bs);
00264 switch (headertype) {
00265 case OBEX_HDR_CONNECTION:
00266 smlTrace(TRACE_INTERNAL, "%s: Found connection number: %d", __func__, header.bq4);
00267 conid = header.bq4;
00268 break;
00269 case OBEX_HDR_TYPE:;
00270 char *mimetypestr = g_strndup((char *)header.bs, len);
00271
00272
00273
00274
00275
00276
00277
00278 smlTrace(TRACE_INTERNAL, "%s: Found type: %s", __func__, VA_STRING(mimetypestr));
00279
00280 if (!strcmp(mimetypestr, SML_ELEMENT_WBXML)) {
00281 mimetype = SML_MIMETYPE_WBXML;
00282 } else if (!strcmp(mimetypestr, SML_ELEMENT_XML)) {
00283 mimetype = SML_MIMETYPE_XML;
00284 } else if (!strcmp(mimetypestr, SML_ELEMENT_SAN)) {
00285 mimetype = SML_MIMETYPE_SAN;
00286 } else {
00287 smlSafeCFree(&mimetypestr);
00288 smlErrorSet(&error, SML_ERROR_GENERIC, "Unknown mime type");
00289 goto error;
00290 }
00291
00292 smlSafeCFree(&mimetypestr);
00293 break;
00294 default:
00295 smlTrace(TRACE_INTERNAL, "%s: Unknown header", __func__);
00296 }
00297 }
00298
00299 if (!conid) {
00300 smlErrorSet(&error, SML_ERROR_GENERIC, "Missing connection id");
00301 goto error;
00302 }
00303
00304 if (conid != linkenv->conid) {
00305 smlErrorSet(&error, SML_ERROR_GENERIC, "Wrong connection id");
00306 goto error;
00307 }
00308
00309 if (mimetype == SML_MIMETYPE_UNKNOWN) {
00310 smlErrorSet(&error, SML_ERROR_GENERIC, "Missing mime type");
00311 goto error;
00312 }
00313
00314 if (linkenv->error) {
00315 if (smlErrorGetClass(&(linkenv->error)) <= SML_ERRORCLASS_RETRY)
00316 OBEX_ObjectSetRsp(object, OBEX_RSP_FORBIDDEN, OBEX_RSP_FORBIDDEN);
00317 else
00318 OBEX_ObjectSetRsp(object, OBEX_RSP_FORBIDDEN, OBEX_RSP_FORBIDDEN);
00319
00320 smlErrorDeref(&(linkenv->error));
00321 linkenv->error = NULL;
00322 smlTrace(TRACE_INTERNAL, "%s: Sent error in response to get", __func__);
00323 break;
00324 }
00325
00326 if (!linkenv->send_data) {
00327 smlErrorSet(&error, SML_ERROR_GENERIC, "No data to send");
00328 goto error;
00329 }
00330
00331 if (mimetype != linkenv->send_data->type) {
00332 smlErrorSet(&error, SML_ERROR_GENERIC,
00333 "Wrong mimetype %d requested. %d was expected.",
00334 mimetype, linkenv->send_data->type);
00335 goto error;
00336 }
00337
00338
00339 header.bq4 = (uint32_t)linkenv->send_data->size;
00340 OBEX_ObjectAddHeader(handle, object, OBEX_HDR_LENGTH, header, sizeof(uint32_t), 0);
00341
00342 header.bs = (unsigned char *)linkenv->send_data->data;
00343 OBEX_ObjectAddHeader(handle, object, OBEX_HDR_BODY, header, linkenv->send_data->size, 0);
00344
00345 smlTransportDataDeref(linkenv->send_data);
00346 linkenv->send_data = NULL;
00347
00348 OBEX_ObjectSetRsp(object, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS);
00349 break;
00350 case OBEX_CMD_CONNECT:;
00351 smlTrace(TRACE_INTERNAL, "%s: Got CONNECT command", __func__);
00352 char *target = NULL;
00353
00354 while (OBEX_ObjectGetNextHeader(handle, object, &headertype, &header, &len)) {
00355 smlTrace(TRACE_INTERNAL, "%s: Next header %i, %d, %p", __func__, headertype, header.bq4, header.bs);
00356 switch (headertype) {
00357 case OBEX_HDR_TARGET:
00358 target = g_strndup((char *)header.bs, len);
00359 smlTrace(TRACE_INTERNAL, "%s: Found target: %s", __func__, VA_STRING(target));
00360 break;
00361 default:
00362 smlTrace(TRACE_INTERNAL, "%s: Unknown header", __func__);
00363 }
00364 }
00365
00366 if (!target || strcmp(target, "SYNCML-SYNC")) {
00367 smlSafeCFree(&target);
00368 smlErrorSet(&error, SML_ERROR_GENERIC, "Missing target");
00369 goto error;
00370 }
00371 smlSafeCFree(&target);
00372
00373 header.bq4 = linkenv->conid;
00374 OBEX_ObjectAddHeader(handle, object, OBEX_HDR_CONNECTION, header, sizeof(linkenv->conid), OBEX_FL_FIT_ONE_PACKET);
00375
00376 header.bs = (unsigned char *)"SYNCML-SYNC";
00377 OBEX_ObjectAddHeader(handle, object, OBEX_HDR_WHO, header, strlen((char *)header.bs), OBEX_FL_FIT_ONE_PACKET);
00378
00379
00380 linkenv->link = smlLinkNew(linkenv->env->tsp, linkenv, &error);
00381 if (!linkenv->link)
00382 goto error;
00383
00384 if (smlTransportReceiveEvent(linkenv->env->tsp, linkenv->link, SML_TRANSPORT_EVENT_CONNECT_DONE, NULL, NULL))
00385 OBEX_ObjectSetRsp(object, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS);
00386 else {
00387 OBEX_ObjectSetRsp(object, OBEX_RSP_FORBIDDEN, OBEX_RSP_FORBIDDEN);
00388 linkenv->disconnect = TRUE;
00389 }
00390 break;
00391 case OBEX_CMD_DISCONNECT:
00392 smlTrace(TRACE_INTERNAL, "%s: Got DISCONNECT command", __func__);
00393 OBEX_ObjectSetRsp(object, OBEX_RSP_SUCCESS, OBEX_RSP_SUCCESS);
00394 break;
00395 default:
00396 smlTrace(TRACE_INTERNAL, "%s: Denied %02x request", __func__, obex_cmd);
00397 OBEX_ObjectSetRsp(object, OBEX_RSP_NOT_IMPLEMENTED, OBEX_RSP_NOT_IMPLEMENTED);
00398 break;
00399 }
00400
00401 break;
00402 case OBEX_EV_LINKERR:
00403 smlTrace(TRACE_INTERNAL, "%s: Link broken (this does not have to be an error)!", __func__);
00404 break;
00405 default:
00406 smlTrace(TRACE_INTERNAL, "%s: Unknown event!", __func__);
00407 break;
00408 }
00409
00410 smlTrace(TRACE_EXIT, "%s", __func__);
00411 return;
00412
00413 error:
00414 OBEX_ObjectSetRsp(object, OBEX_RSP_BAD_REQUEST, OBEX_RSP_BAD_REQUEST);
00415 smlErrorRef(&error);
00416 smlTransportReceiveEvent(linkenv->env->tsp, linkenv->link, SML_TRANSPORT_EVENT_ERROR, NULL, error);
00417 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&error));
00418 smlErrorDeref(&error);
00419 }
00420
00421 static void _smlTransportObexServerMainEvent(obex_t *handle, obex_object_t *object, int mode, int event, int obex_cmd, int obex_rsp)
00422 {
00423 smlTrace(TRACE_ENTRY, "%s(%p, %p, %i, %i, %i, %i)",
00424 __func__, handle, object, mode, event, obex_cmd, obex_rsp);
00425 SmlTransportObexServerEnv *env = OBEX_GetUserData(handle);
00426 SmlError *error = NULL;
00427 SmlLinkObexServerEnv *linkenv = NULL;
00428
00429 switch (event) {
00430 case OBEX_EV_ACCEPTHINT:
00431
00432
00433
00434 linkenv = smlTryMalloc0(sizeof(SmlLinkObexServerEnv), &error);
00435 if (!linkenv)
00436 goto error;
00437 linkenv->env = env;
00438
00439 linkenv->handle = OBEX_ServerAccept(env->handle, _smlTransportObexServerLinkEvent, linkenv);
00440 if (!linkenv->handle) {
00441 smlErrorSet(&error, SML_ERROR_GENERIC,
00442 "OBEX_ServerAccept failed.");
00443 smlSafeFree((gpointer *)&linkenv);
00444 goto error;
00445 }
00446 smlTrace(TRACE_INTERNAL, "%s: New obex_t * handle %p", __func__, linkenv->handle);
00447
00448
00449 linkenv->source = g_idle_source_new();
00450 g_source_set_callback(linkenv->source, _dispatch_obex, linkenv, NULL);
00451 g_source_attach(linkenv->source, env->tsp->context);
00452 if (env->tsp->context)
00453 g_main_context_ref(env->tsp->context);
00454
00455
00456 env->lastConId++;
00457 linkenv->conid = env->lastConId;
00458
00459
00460
00461
00462 break;
00463 default:
00464 smlErrorSet(&error, SML_ERROR_GENERIC,
00465 "Unknown OBEX event %d.", event);
00466 goto error;
00467 break;
00468 }
00469
00470 smlTrace(TRACE_EXIT, "%s", __func__);
00471 return;
00472
00473 error:
00474 OBEX_ObjectSetRsp(object, OBEX_RSP_BAD_REQUEST, OBEX_RSP_BAD_REQUEST);
00475 smlErrorRef(&error);
00476 smlTransportReceiveEvent(env->tsp, NULL, SML_TRANSPORT_EVENT_ERROR, NULL, error);
00477 smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(&error));
00478 smlErrorDeref(&error);
00479 }
00480
00481
00482
00483 static gboolean _fd_prepare(GSource *source, gint *timeout_)
00484 {
00485 smlTrace(TRACE_INTERNAL, "%s(%p, %p)", __func__, source, timeout_);
00486
00487
00488
00489 *timeout_ = 50;
00490 return FALSE;
00491 }
00492
00493 static gboolean _fd_check(GSource *source)
00494 {
00495 SmlTransportObexServerEnv *env = *((SmlTransportObexServerEnv **)(source + 1));
00496
00497 fd_set rfds;
00498 FD_ZERO(&rfds);
00499 int fd = OBEX_GetFD(env->handle);
00500 FD_SET(fd, &rfds);
00501
00502 struct timeval tv;
00503 tv.tv_sec = 0;
00504 tv.tv_usec = 1;
00505
00506 int retval = select(fd + 1, &rfds, NULL, NULL, &tv);
00507
00508 if (retval == -1)
00509 smlTrace(TRACE_ERROR, "%s: Unable to select()", __func__);
00510 else if (retval)
00511 return TRUE;
00512
00513 return FALSE;
00514 }
00515
00516 static gboolean _fd_dispatch(GSource *source, GSourceFunc callback, gpointer user_data)
00517 {
00518 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, source, callback, user_data);
00519 SmlTransportObexServerEnv *env = user_data;
00520 SmlError *error = NULL;
00521
00522
00523 int result = OBEX_HandleInput(env->handle, 0);
00524 if (result < 0) {
00525 smlErrorSet(&error, SML_ERROR_GENERIC,
00526 "OBEX_HandleInput on main handle returned %d.",
00527 result);
00528 goto error;
00529 }
00530 if (result == 0) {
00531 smlErrorSet(&error, SML_ERROR_GENERIC,
00532 "OBEX_HandleInput on main handle get a timeout.");
00533 goto error;
00534 }
00535
00536 smlTrace(TRACE_EXIT, "%s", __func__);
00537 return TRUE;
00538 error:
00539 smlTransportReceiveEvent(env->tsp, NULL, SML_TRANSPORT_EVENT_ERROR, NULL, error);
00540 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&error));
00541 return FALSE;
00542 }
00543
00544 static SmlBool smlTransportObexServerSetConfigOption(
00545 SmlTransport *tsp,
00546 const char *name,
00547 const char *value,
00548 SmlError **error)
00549 {
00550 smlTrace(TRACE_ENTRY, "%s(%p, %s, %s, %p)", __func__, tsp, VA_STRING(name), VA_STRING(value), error);
00551 CHECK_ERROR_REF
00552 smlAssert(tsp);
00553 smlAssert(tsp->transport_data);
00554 SmlTransportObexServerEnv *env = tsp->transport_data;
00555
00556 if (!strcmp(name, SML_TRANSPORT_CONFIG_PORT)) {
00557 env->port = atoi(value);
00558 smlTrace(TRACE_INTERNAL, "%s: Port %i detected", __func__, env->port);
00559 } else if (!strcmp(name, SML_TRANSPORT_CONFIG_BLUETOOTH_ADDRESS)) {
00560 #ifdef ENABLE_BLUETOOTH
00561 int code = str2ba(value, env->bdaddr);
00562 if (code != 0) {
00563 smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION,
00564 "Bluetooth MAC cannot be interpreted (%d).", code);
00565 goto error;
00566 }
00567 smlTrace(TRACE_INTERNAL, "%s: Bluetooth MAC %s detected",
00568 __func__, VA_STRING(value));
00569 #else
00570 smlErrorSet(error, SML_ERROR_GENERIC, "Bluetooth not enabled");
00571 goto error;
00572 #endif
00573 } else if (!strcmp(name, SML_TRANSPORT_CONFIG_BLUETOOTH_CHANNEL)) {
00574 env->port = atoi(value);
00575 smlTrace(TRACE_INTERNAL, "%s: Bluetooth channel %i detected",
00576 __func__, env->port);
00577 } else if (!strcmp(name, SML_TRANSPORT_CONFIG_IRDA_SERVICE)) {
00578 env->irda_service = g_strdup(value);
00579 smlTrace(TRACE_INTERNAL, "%s: IRDA service %s detected",
00580 __func__, VA_STRING(env->irda_service));
00581 } else {
00582 smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION,
00583 "Unknown parameter %s found.", name);
00584 goto error;
00585 }
00586
00587 smlTrace(TRACE_EXIT, "%s - TRUE", __func__);
00588 return TRUE;
00589 error:
00590 smlTrace(TRACE_EXIT, "%s - %s", __func__, smlErrorPrint(error));
00591 return FALSE;
00592 }
00593
00594 static SmlBool smlTransportObexServerSetConnectionType(
00595 SmlTransport *tsp,
00596 SmlTransportConnectionType type,
00597 SmlError **error)
00598 {
00599 smlTrace(TRACE_ENTRY, "%s(%p, %i, %p)", __func__, tsp, type, error);
00600 CHECK_ERROR_REF
00601 smlAssert(tsp);
00602 smlAssert(tsp->transport_data);
00603 SmlTransportObexServerEnv *env = tsp->transport_data;
00604
00605 env->type = type;
00606
00607 smlTrace(TRACE_EXIT, "%s", __func__);
00608 return TRUE;
00609 }
00610
00611 static SmlBool smlTransportObexServerInit(SmlTransport *tsp, SmlError **error)
00612 {
00613 smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, tsp, error);
00614 CHECK_ERROR_REF
00615 smlAssert(tsp);
00616 smlAssert(tsp->transport_data);
00617 SmlTransportObexServerEnv *env = tsp->transport_data;
00618 smlAssert(env->handle == NULL);
00619
00620 switch (env->type) {
00621 #ifdef ENABLE_OPENOBEX_TCP
00622 case SML_TRANSPORT_CONNECTION_TYPE_NET:;
00623
00624 env->handle = OBEX_Init(OBEX_TRANS_INET,
00625 _smlTransportObexServerMainEvent,
00626 OBEX_FL_KEEPSERVER);
00627 if (!env->handle) {
00628 smlErrorSet(error, SML_ERROR_GENERIC,
00629 "Unable to create OBEX IRDA transport.");
00630 goto error;
00631 }
00632 OBEX_SetUserData(env->handle, env);
00633
00634 if (!env->port)
00635 g_warning("Using default INET port.");
00636 size_t size = sizeof(struct sockaddr_in);
00637 struct sockaddr_in *addr = smlTryMalloc0(size, error);
00638 if (!addr)
00639 goto error;
00640 addr->sin_family = PF_INET;
00641 addr->sin_port = htons(env->port);
00642 addr->sin_addr.s_addr = INADDR_ANY;
00643
00644 if (GET_OBEX_RESULT(TcpOBEX_ServerRegister(env->handle, (struct sockaddr *) addr, size)) < 0)
00645 {
00646 smlErrorSet(error, SML_ERROR_GENERIC,
00647 "Unable to register INET OBEX server. %s (%i).",
00648 strerror(errno), errno);
00649 smlSafeFree((gpointer *)&addr);
00650 goto error;
00651 }
00652 smlSafeFree((gpointer *)&addr);
00653 break;
00654 #endif
00655 case SML_TRANSPORT_CONNECTION_TYPE_SERIAL:
00656
00657 env->handle = OBEX_Init(OBEX_TRANS_IRDA,
00658 _smlTransportObexServerMainEvent,
00659 OBEX_FL_KEEPSERVER);
00660 if (!env->handle) {
00661 smlErrorSet(error, SML_ERROR_GENERIC,
00662 "Unable to create OBEX IRDA transport.");
00663 goto error;
00664 }
00665 OBEX_SetUserData(env->handle, env);
00666
00667 if (GET_OBEX_RESULT(IrOBEX_ServerRegister(env->handle, env->irda_service)))
00668 {
00669 smlErrorSet(error, SML_ERROR_GENERIC,
00670 "Unable to register IRDA OBEX server. %s (%i).",
00671 strerror(errno), errno);
00672 goto error;
00673 }
00674 break;
00675 case SML_TRANSPORT_CONNECTION_TYPE_BLUETOOTH:
00676 #ifdef ENABLE_BLUETOOTH
00677
00678 env->handle = OBEX_Init(OBEX_TRANS_BLUETOOTH,
00679 _smlTransportObexServerMainEvent,
00680 OBEX_FL_KEEPSERVER);
00681 if (!env->handle) {
00682 smlErrorSet(error, SML_ERROR_GENERIC,
00683 "Unable to create OBEX Bluetooth transport.");
00684 goto error;
00685 }
00686 OBEX_SetUserData(env->handle, env);
00687
00688 if (GET_OBEX_RESULT(BtOBEX_ServerRegister(env->handle, env->bdaddr, env->port)) < 0)
00689 {
00690 smlErrorSet(error, SML_ERROR_GENERIC,
00691 "Unable to register Bluetooth OBEX server. %s (%i).",
00692 strerror(errno), errno);
00693 goto error;
00694 }
00695 #else
00696 smlErrorSet(error, SML_ERROR_GENERIC, "Bluetooth not enabled");
00697 goto error;
00698 #endif
00699 break;
00700 default:
00701 smlErrorSet(error, SML_ERROR_GENERIC, "Unknown obex type");
00702 goto error;
00703 }
00704 smlTrace(TRACE_INTERNAL, "%s: server registered successfully", __func__);
00705
00706
00707 env->functions = smlTryMalloc0(sizeof(GSourceFuncs), error);
00708 if (!env->functions)
00709 goto error;
00710 env->functions->prepare = _fd_prepare;
00711 env->functions->check = _fd_check;
00712 env->functions->dispatch = _fd_dispatch;
00713 env->functions->finalize = NULL;
00714
00715 env->source = g_source_new(env->functions, sizeof(GSource) + sizeof(SmlTransportObexServerEnv *));
00716 SmlTransportObexServerEnv **envptr = (SmlTransportObexServerEnv **)(env->source + 1);
00717 *envptr = env;
00718 g_source_set_callback(env->source, NULL, env, NULL);
00719 g_source_attach(env->source, tsp->context);
00720 if (tsp->context)
00721 g_main_context_ref(tsp->context);
00722
00723 smlTrace(TRACE_EXIT, "%s: %p", __func__, env);
00724 return TRUE;
00725
00726 error:
00727 if (env->handle) {
00728 OBEX_Cleanup(env->handle);
00729 env->handle = NULL;
00730 }
00731 if (env)
00732 smlSafeFree((gpointer *)&env);
00733 smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error));
00734 return FALSE;
00735 }
00736
00737 static SmlBool smlTransportObexServerFinalize(void *data, SmlError **error)
00738 {
00739 smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, data, error);
00740 CHECK_ERROR_REF
00741 smlAssert(data);
00742 SmlTransportObexServerEnv *env = data;
00743
00744 smlAssert(env->tsp);
00745
00746 if (env->handle)
00747 OBEX_Cleanup(env->handle);
00748
00749
00750 if (env->source) {
00751 g_source_destroy(env->source);
00752 g_source_unref(env->source);
00753 }
00754
00755
00756 if (env->tsp->context)
00757 g_main_context_unref(env->tsp->context);
00758
00759
00760 if (env->functions)
00761 smlSafeFree((gpointer *)&(env->functions));
00762
00763
00764 if (env->irda_service)
00765 smlSafeCFree(&(env->irda_service));
00766
00767 smlSafeFree((gpointer *)&env);
00768
00769 smlTrace(TRACE_EXIT, "%s", __func__);
00770 return TRUE;
00771 }
00772
00773 static void smlTransportObexServerSend(void *userdata, void *linkdata, SmlTransportData *data, SmlError *error)
00774 {
00775 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, userdata, linkdata, data, error);
00776 smlAssert(data || error);
00777 smlAssert(userdata);
00778
00779 SmlLinkObexServerEnv *linkenv = linkdata;
00780 smlAssert(linkenv);
00781 SmlError *local_error = NULL;
00782
00783 if (linkdata == NULL) {
00784
00785
00786
00787 smlErrorSet(&local_error, SML_ERROR_GENERIC,
00788 "The OBEX server tries to send before a connection with a client was established or the link was ignored.");
00789 goto error;
00790 }
00791
00792 if (error) {
00793 smlAssert(!data);
00794 linkenv->error = error;
00795
00796 smlTrace(TRACE_EXIT, "%s: Error set", __func__);
00797 return;
00798 }
00799
00800 if (linkenv->send_data) {
00801 smlErrorSet(&local_error, SML_ERROR_GENERIC, "We already have waiting data");
00802 goto error;
00803 }
00804
00805 linkenv->send_data = data;
00806 smlTransportDataRef(linkenv->send_data);
00807
00808 smlTrace(TRACE_EXIT, "%s", __func__);
00809 return;
00810
00811 error:
00812 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&local_error));
00813 smlTransportReceiveEvent(linkenv->env->tsp, linkenv->link, SML_TRANSPORT_EVENT_ERROR, NULL, local_error);
00814 smlErrorDeref(&local_error);
00815 return;
00816 }
00817
00818 static void smlTransportObexServerDisconnect(void *data, void *linkdata)
00819 {
00820 smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, data, linkdata);
00821 smlAssert(data);
00822
00823
00824
00825
00826
00827
00828 if (linkdata) {
00829 SmlLinkObexServerEnv *linkenv = linkdata;
00830 linkenv->disconnect = TRUE;
00831 smlTrace(TRACE_ERROR, "%s - explicit disconnect by OBEX server", __func__);
00832 }
00833
00834 smlTrace(TRACE_EXIT, "%s", __func__);
00835 return;
00836 }
00837
00838 SmlBool smlTransportObexServerNew(SmlTransport *tsp, SmlError **error)
00839 {
00840 CHECK_ERROR_REF
00841 smlAssert(tsp);
00842
00843 tsp->functions.set_config_option = smlTransportObexServerSetConfigOption;
00844 tsp->functions.set_connection_type = smlTransportObexServerSetConnectionType;
00845 tsp->functions.initialize = smlTransportObexServerInit;
00846 tsp->functions.finalize = smlTransportObexServerFinalize;
00847 tsp->functions.send = smlTransportObexServerSend;
00848 tsp->functions.disconnect = smlTransportObexServerDisconnect;
00849
00850 SmlTransportObexServerEnv *env = smlTryMalloc0(sizeof(SmlTransportObexServerEnv), error);
00851 if (!env)
00852 return FALSE;
00853 tsp->transport_data = env;
00854 env->tsp = tsp;
00855 env->lastConId = 0;
00856 env->port = 0;
00857
00858 return TRUE;
00859 }
00860