int csm_add_service(csm_service_list *services, csm_service *s, csm_ctx *ctx) { // validate service fields against schema CHECK(csm_validate_fields(ctx, s), "Service doesn't validate"); // attach service to service list s->parent = services; // co_obj_t *service_obj = co_service_create(s); // CHECK_MEM(service_obj); co_service_t *service_obj = container_of(s, co_service_t, service); CHECK(co_list_append(services->services, (co_obj_t *)service_obj), "Failed to add service to service list"); co_obj_t *fields = s->fields; // detach s->fields from s before adding s->fields to services->service_fields hattach(fields, NULL); // add service fields to service list CHECK(co_list_append(services->service_fields, fields), "Failed to add service fields to service list"); CHECK(csm_update_service(services, s, ctx, 0), "Failed to finalize service"); return 1; error: csm_remove_service(services, s); // csm_service_destroy(s); return 0; }
int co_request_append_uint(co_obj_t *request, const unsigned int i) { CHECK_MEM(request); CHECK(IS_LIST(request), "Not a valid request."); CHECK(i < UINT64_MAX, "Integer out of bounds."); if(i > UINT32_MAX) return co_list_append(request, co_uint64_create(i, 0)); if(i > UINT16_MAX) return co_list_append(request, co_uint32_create(i, 0)); if(i > UINT8_MAX) return co_list_append(request, co_uint16_create(i, 0)); return co_list_append(request, co_uint8_create(i, 0)); error: return 0; }
int co_request_append_int(co_obj_t *request, const int i) { CHECK_MEM(request); CHECK(IS_LIST(request), "Not a valid request."); CHECK(i < INT64_MAX && i > INT64_MIN, "Integer out of bounds."); if(i > INT32_MAX || i < INT32_MIN) return co_list_append(request, co_int64_create(i, 0)); if(i > INT16_MAX || i < INT16_MIN) return co_list_append(request, co_int32_create(i, 0)); if(i > INT8_MAX || i < INT8_MIN) return co_list_append(request, co_int16_create(i, 0)); return co_list_append(request, co_int8_create(i, 0)); error: return 0; }
int co_request_append_bin(co_obj_t *request, const char *s, const size_t slen) { CHECK_MEM(request); CHECK_MEM(s); CHECK(IS_LIST(request), "Not a valid request."); CHECK(slen < UINT32_MAX, "Binary is too large."); if(slen > UINT16_MAX) return co_list_append(request, co_bin32_create(s, slen, 0)); if(slen > UINT8_MAX) return co_list_append(request, co_bin16_create(s, slen, 0)); return co_list_append(request, co_bin8_create(s, slen, 0)); error: return 0; }
int co_request_append(co_obj_t *request, co_obj_t *object) { CHECK_MEM(request); CHECK_MEM(object); CHECK(IS_LIST(request), "Not a valid request."); return co_list_append(request, object); error: return 0; }
co_obj_t * co_connect(const char *uri, const size_t ulen) { CHECK_MEM(_sockets); CHECK(uri != NULL && ulen > 0, "Invalid URI."); co_obj_t *socket = NEW(co_socket, unix_socket); hattach(socket, _pool); CHECK((((co_socket_t*)socket)->connect(socket, uri)), "Failed to connect to commotiond at %s\n", uri); co_list_append(_sockets, socket); return socket; error: co_obj_free(socket); return NULL; }
/** * update handlers must be idempotent and side effect free, as * handlers are called in the order they were registered with * service list */ int csm_services_register_commit_hook(csm_service_list *services, co_cb_t handler) { co_cbptr_t *callback = h_calloc(1, sizeof(co_cbptr_t)); CHECK_MEM(callback); callback->_header._type = _ext8; callback->_header._ref = 0; callback->_header._flags = 0; callback->_exttype = _cbptr; callback->_len = sizeof(co_cb_t *); callback->cb = handler; CHECK(co_list_append(services->update_handlers, (co_obj_t *)callback), "Failed to register commit hook"); return 1; error: return 0; }
int csm_update_service(csm_service_list *services, csm_service *s, csm_ctx *ctx, int validate) { if (validate) CHECK(csm_validate_fields(ctx, s), "Service doesn't validate"); // assert(s->lifetime); long lifetime = s->lifetime; // check if service is attached to service_list CHECK(co_list_contains(services->services, (co_obj_t*)container_of(s, co_service_t, service)), "Cannot update service not in service list"); // detach s->fields from s and attach to services->service_fields if (!co_list_contains(services->service_fields, s->fields)) { co_obj_t *fields = s->fields; hattach(fields, NULL); CHECK(co_list_append(services->service_fields, fields), "Failed to add service fields to service list"); } /* Create or verify signature */ if (s->signature) CHECK(csm_verify_signature(s),"Invalid signature"); else CHECK(csm_create_signature(s),"Failed to create signature"); /* Set expiration timer on the service */ #ifdef USE_UCI long def_lifetime = default_lifetime(); if (lifetime == 0 || (def_lifetime < lifetime && def_lifetime > 0)) lifetime = def_lifetime; #endif if (lifetime > 0) { struct timeval tv; avahi_elapse_time(&tv, 1000*lifetime, 0); time_t current_time = time(NULL); // create expiration event for service s->timeout = avahi_simple_poll_get(simple_poll)->timeout_new(avahi_simple_poll_get(simple_poll), &tv, _csm_expire_service, s); /* Convert lifetime period into timestamp */ if (current_time != ((time_t)-1)) { struct tm *timestr = localtime(¤t_time); timestr->tm_sec += lifetime; current_time = mktime(timestr); char *c_time_string = ctime(¤t_time); if (c_time_string) { c_time_string[strlen(c_time_string)-1] = '\0'; /* ctime adds \n to end of time string; remove it */ s->expiration = h_strdup(c_time_string); CHECK_MEM(s->expiration); service_attach(s->expiration, s); } } } // finalize service by running update handlers csm_services_commit(services); return 1; error: return 0; }